diff --git a/core/java/android/content/res/Element.java b/core/java/android/content/res/Element.java
index 62a46b6b71525..3e0ab90f99d24 100644
--- a/core/java/android/content/res/Element.java
+++ b/core/java/android/content/res/Element.java
@@ -16,6 +16,8 @@
package android.content.res;
+import static android.os.SystemProperties.PROP_VALUE_MAX;
+
import android.annotation.NonNull;
import android.util.Pools.SimplePool;
@@ -23,9 +25,6 @@ import androidx.annotation.StyleableRes;
import com.android.internal.R;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
/**
* Defines the string attribute length and child tag count restrictions for a xml element.
*
@@ -34,8 +33,13 @@ import org.xmlpull.v1.XmlPullParserException;
public class Element {
private static final int DEFAULT_MAX_STRING_ATTR_LENGTH = 32_768;
private static final int MAX_POOL_SIZE = 128;
-
- private static final String ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android";
+ private static final int MAX_ATTR_LEN_URL_COMPONENT = 256;
+ private static final int MAX_ATTR_LEN_PERMISSION_GROUP = 256;
+ private static final int MAX_ATTR_LEN_PACKAGE = 256;
+ private static final int MAX_ATTR_LEN_MIMETYPE = 512;
+ public static final int MAX_ATTR_LEN_NAME = 1024;
+ public static final int MAX_ATTR_LEN_PATH = 4000;
+ public static final int MAX_ATTR_LEN_DATA_VALUE = 4000;
protected static final String TAG_ACTION = "action";
protected static final String TAG_ACTIVITY = "activity";
@@ -123,43 +127,9 @@ public class Element {
protected static final String TAG_ATTR_VERSION_NAME = "versionName";
protected static final String TAG_ATTR_WRITE_PERMISSION = "writePermission";
- private static final String[] ACTIVITY_STR_ATTR_NAMES = {TAG_ATTR_NAME,
- TAG_ATTR_PARENT_ACTIVITY_NAME, TAG_ATTR_PERMISSION, TAG_ATTR_PROCESS,
- TAG_ATTR_TASK_AFFINITY};
- private static final String[] ACTIVITY_ALIAS_STR_ATTR_NAMES = {TAG_ATTR_NAME,
- TAG_ATTR_PERMISSION, TAG_ATTR_TARGET_ACTIVITY};
- private static final String[] APPLICATION_STR_ATTR_NAMES = {TAG_ATTR_BACKUP_AGENT,
- TAG_ATTR_MANAGE_SPACE_ACTIVITY, TAG_ATTR_NAME, TAG_ATTR_PERMISSION, TAG_ATTR_PROCESS,
- TAG_ATTR_REQUIRED_ACCOUNT_TYPE, TAG_ATTR_RESTRICTED_ACCOUNT_TYPE,
- TAG_ATTR_TASK_AFFINITY};
- private static final String[] DATA_STR_ATTR_NAMES = {TAG_ATTR_SCHEME, TAG_ATTR_HOST,
- TAG_ATTR_PORT, TAG_ATTR_PATH, TAG_ATTR_PATH_PATTERN, TAG_ATTR_PATH_PREFIX,
- TAG_ATTR_PATH_SUFFIX, TAG_ATTR_PATH_ADVANCED_PATTERN, TAG_ATTR_MIMETYPE};
- private static final String[] GRANT_URI_PERMISSION_STR_ATTR_NAMES = {TAG_ATTR_PATH,
- TAG_ATTR_PATH_PATTERN, TAG_ATTR_PATH_PREFIX};
- private static final String[] INSTRUMENTATION_STR_ATTR_NAMES = {TAG_ATTR_NAME,
- TAG_ATTR_TARGET_PACKAGE, TAG_ATTR_TARGET_PROCESSES};
- private static final String[] MANIFEST_STR_ATTR_NAMES = {TAG_ATTR_PACKAGE,
- TAG_ATTR_SHARED_USER_ID, TAG_ATTR_VERSION_NAME};
- private static final String[] OVERLAY_STR_ATTR_NAMES = {TAG_ATTR_CATEGORY,
- TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_NAME, TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_VALUE,
- TAG_ATTR_TARGET_PACKAGE, TAG_ATTR_TARGET_NAME};
- private static final String[] PATH_PERMISSION_STR_ATTR_NAMES = {TAG_ATTR_PATH,
- TAG_ATTR_PATH_PREFIX, TAG_ATTR_PATH_PATTERN, TAG_ATTR_PERMISSION,
- TAG_ATTR_READ_PERMISSION, TAG_ATTR_WRITE_PERMISSION};
- private static final String[] PERMISSION_STR_ATTR_NAMES = {TAG_ATTR_NAME,
- TAG_ATTR_PERMISSION_GROUP};
- private static final String[] PROVIDER_STR_ATTR_NAMES = {TAG_ATTR_NAME, TAG_ATTR_PERMISSION,
- TAG_ATTR_PROCESS, TAG_ATTR_READ_PERMISSION, TAG_ATTR_WRITE_PERMISSION};
- private static final String[] RECEIVER_SERVICE_STR_ATTR_NAMES = {TAG_ATTR_NAME,
- TAG_ATTR_PERMISSION, TAG_ATTR_PROCESS};
- private static final String[] NAME_ATTR = {TAG_ATTR_NAME};
- private static final String[] NAME_VALUE_ATTRS = {TAG_ATTR_NAME, TAG_ATTR_VALUE};
-
- private String[] mStringAttrNames = new String[0];
// The length of mTagCounters corresponds to the number of tags defined in getCounterIdx. If new
// tags are added then the size here should be increased to match.
- private final TagCounter[] mTagCounters = new TagCounter[35];
+ private final TagCounter[] mTagCounters = new TagCounter[34];
String mTag;
@@ -177,7 +147,6 @@ public class Element {
}
void recycle() {
- mStringAttrNames = new String[0];
mTag = null;
sPool.get().release(this);
}
@@ -230,33 +199,79 @@ public class Element {
return 20;
case TAG_USES_CONFIGURATION:
return 21;
- case TAG_USES_PERMISSION_SDK_23:
- return 22;
case TAG_USES_SDK:
- return 23;
+ return 22;
case TAG_COMPATIBLE_SCREENS:
- return 24;
+ return 23;
case TAG_QUERIES:
- return 25;
+ return 24;
case TAG_ATTRIBUTION:
- return 26;
+ return 25;
case TAG_USES_FEATURE:
- return 27;
+ return 26;
case TAG_PERMISSION:
- return 28;
+ return 27;
case TAG_USES_PERMISSION:
- return 29;
+ case TAG_USES_PERMISSION_SDK_23:
+ case TAG_USES_PERMISSION_SDK_M:
+ return 28;
case TAG_GRANT_URI_PERMISSION:
- return 30;
+ return 29;
case TAG_PATH_PERMISSION:
- return 31;
+ return 30;
case TAG_PACKAGE:
- return 32;
+ return 31;
case TAG_INTENT:
- return 33;
+ return 32;
default:
// The size of the mTagCounters array should be equal to this value+1
- return 34;
+ return 33;
+ }
+ }
+
+ static boolean shouldValidate(String tag) {
+ switch (tag) {
+ case TAG_ACTION:
+ case TAG_ACTIVITY:
+ case TAG_ACTIVITY_ALIAS:
+ case TAG_APPLICATION:
+ case TAG_ATTRIBUTION:
+ case TAG_CATEGORY:
+ case TAG_COMPATIBLE_SCREENS:
+ case TAG_DATA:
+ case TAG_GRANT_URI_PERMISSION:
+ case TAG_INSTRUMENTATION:
+ case TAG_INTENT:
+ case TAG_INTENT_FILTER:
+ case TAG_LAYOUT:
+ case TAG_MANIFEST:
+ case TAG_META_DATA:
+ case TAG_OVERLAY:
+ case TAG_PACKAGE:
+ case TAG_PATH_PERMISSION:
+ case TAG_PERMISSION:
+ case TAG_PERMISSION_GROUP:
+ case TAG_PERMISSION_TREE:
+ case TAG_PROFILEABLE:
+ case TAG_PROPERTY:
+ case TAG_PROVIDER:
+ case TAG_QUERIES:
+ case TAG_RECEIVER:
+ case TAG_SCREEN:
+ case TAG_SERVICE:
+ case TAG_SUPPORTS_GL_TEXTURE:
+ case TAG_SUPPORTS_SCREENS:
+ case TAG_USES_CONFIGURATION:
+ case TAG_USES_FEATURE:
+ case TAG_USES_LIBRARY:
+ case TAG_USES_NATIVE_LIBRARY:
+ case TAG_USES_PERMISSION:
+ case TAG_USES_PERMISSION_SDK_23:
+ case TAG_USES_PERMISSION_SDK_M:
+ case TAG_USES_SDK:
+ return true;
+ default:
+ return false;
}
}
@@ -264,55 +279,31 @@ public class Element {
this.mTag = tag;
mChildTagMask = 0;
switch (tag) {
- case TAG_ACTION:
- case TAG_CATEGORY:
- case TAG_PACKAGE:
- case TAG_PERMISSION_GROUP:
- case TAG_PERMISSION_TREE:
- case TAG_SUPPORTS_GL_TEXTURE:
- case TAG_USES_FEATURE:
- case TAG_USES_LIBRARY:
- case TAG_USES_NATIVE_LIBRARY:
- case TAG_USES_PERMISSION:
- case TAG_USES_PERMISSION_SDK_23:
- case TAG_USES_SDK:
- setStringAttrNames(NAME_ATTR);
- break;
case TAG_ACTIVITY:
- setStringAttrNames(ACTIVITY_STR_ATTR_NAMES);
initializeCounter(TAG_LAYOUT, 1000);
- initializeCounter(TAG_META_DATA, 8000);
+ initializeCounter(TAG_META_DATA, 1000);
initializeCounter(TAG_INTENT_FILTER, 20000);
break;
case TAG_ACTIVITY_ALIAS:
- setStringAttrNames(ACTIVITY_ALIAS_STR_ATTR_NAMES);
- initializeCounter(TAG_META_DATA, 8000);
+ case TAG_RECEIVER:
+ case TAG_SERVICE:
+ initializeCounter(TAG_META_DATA, 1000);
initializeCounter(TAG_INTENT_FILTER, 20000);
break;
case TAG_APPLICATION:
- setStringAttrNames(APPLICATION_STR_ATTR_NAMES);
initializeCounter(TAG_PROFILEABLE, 100);
initializeCounter(TAG_USES_NATIVE_LIBRARY, 100);
initializeCounter(TAG_RECEIVER, 1000);
initializeCounter(TAG_SERVICE, 1000);
+ initializeCounter(TAG_META_DATA, 1000);
+ initializeCounter(TAG_USES_LIBRARY, 1000);
initializeCounter(TAG_ACTIVITY_ALIAS, 4000);
- initializeCounter(TAG_USES_LIBRARY, 4000);
initializeCounter(TAG_PROVIDER, 8000);
- initializeCounter(TAG_META_DATA, 8000);
initializeCounter(TAG_ACTIVITY, 40000);
break;
case TAG_COMPATIBLE_SCREENS:
initializeCounter(TAG_SCREEN, 4000);
break;
- case TAG_DATA:
- setStringAttrNames(DATA_STR_ATTR_NAMES);
- break;
- case TAG_GRANT_URI_PERMISSION:
- setStringAttrNames(GRANT_URI_PERMISSION_STR_ATTR_NAMES);
- break;
- case TAG_INSTRUMENTATION:
- setStringAttrNames(INSTRUMENTATION_STR_ATTR_NAMES);
- break;
case TAG_INTENT:
case TAG_INTENT_FILTER:
initializeCounter(TAG_ACTION, 20000);
@@ -320,7 +311,6 @@ public class Element {
initializeCounter(TAG_DATA, 40000);
break;
case TAG_MANIFEST:
- setStringAttrNames(MANIFEST_STR_ATTR_NAMES);
initializeCounter(TAG_APPLICATION, 100);
initializeCounter(TAG_OVERLAY, 100);
initializeCounter(TAG_INSTRUMENTATION, 100);
@@ -329,7 +319,6 @@ public class Element {
initializeCounter(TAG_SUPPORTS_GL_TEXTURE, 100);
initializeCounter(TAG_SUPPORTS_SCREENS, 100);
initializeCounter(TAG_USES_CONFIGURATION, 100);
- initializeCounter(TAG_USES_PERMISSION_SDK_23, 100);
initializeCounter(TAG_USES_SDK, 100);
initializeCounter(TAG_COMPATIBLE_SCREENS, 200);
initializeCounter(TAG_QUERIES, 200);
@@ -338,24 +327,10 @@ public class Element {
initializeCounter(TAG_PERMISSION, 2000);
initializeCounter(TAG_USES_PERMISSION, 20000);
break;
- case TAG_META_DATA:
- case TAG_PROPERTY:
- setStringAttrNames(NAME_VALUE_ATTRS);
- break;
- case TAG_OVERLAY:
- setStringAttrNames(OVERLAY_STR_ATTR_NAMES);
- break;
- case TAG_PATH_PERMISSION:
- setStringAttrNames(PATH_PERMISSION_STR_ATTR_NAMES);
- break;
- case TAG_PERMISSION:
- setStringAttrNames(PERMISSION_STR_ATTR_NAMES);
- break;
case TAG_PROVIDER:
- setStringAttrNames(PROVIDER_STR_ATTR_NAMES);
initializeCounter(TAG_GRANT_URI_PERMISSION, 100);
initializeCounter(TAG_PATH_PERMISSION, 100);
- initializeCounter(TAG_META_DATA, 8000);
+ initializeCounter(TAG_META_DATA, 1000);
initializeCounter(TAG_INTENT_FILTER, 20000);
break;
case TAG_QUERIES:
@@ -363,39 +338,23 @@ public class Element {
initializeCounter(TAG_INTENT, 2000);
initializeCounter(TAG_PROVIDER, 8000);
break;
- case TAG_RECEIVER:
- case TAG_SERVICE:
- setStringAttrNames(RECEIVER_SERVICE_STR_ATTR_NAMES);
- initializeCounter(TAG_META_DATA, 8000);
- initializeCounter(TAG_INTENT_FILTER, 20000);
- break;
}
}
- private void setStringAttrNames(String[] attrNames) {
- mStringAttrNames = attrNames;
- }
-
- private static String getAttrNamespace(String attrName) {
- if (attrName.equals(TAG_ATTR_PACKAGE)) {
- return null;
- }
- return ANDROID_NAMESPACE;
- }
-
- private static int getAttrStringMaxLength(String attrName) {
+ private static int getAttrStrMaxLen(String attrName) {
switch (attrName) {
case TAG_ATTR_HOST:
- case TAG_ATTR_PACKAGE:
- case TAG_ATTR_PERMISSION_GROUP:
case TAG_ATTR_PORT:
- case TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_VALUE:
case TAG_ATTR_SCHEME:
+ return MAX_ATTR_LEN_URL_COMPONENT;
+ case TAG_ATTR_PERMISSION_GROUP:
+ return MAX_ATTR_LEN_PERMISSION_GROUP;
case TAG_ATTR_SHARED_USER_ID:
+ case TAG_ATTR_PACKAGE:
case TAG_ATTR_TARGET_PACKAGE:
- return 256;
+ return MAX_ATTR_LEN_PACKAGE;
case TAG_ATTR_MIMETYPE:
- return 512;
+ return MAX_ATTR_LEN_MIMETYPE;
case TAG_ATTR_BACKUP_AGENT:
case TAG_ATTR_CATEGORY:
case TAG_ATTR_MANAGE_SPACE_ACTIVITY:
@@ -405,33 +364,343 @@ public class Element {
case TAG_ATTR_PROCESS:
case TAG_ATTR_READ_PERMISSION:
case TAG_ATTR_REQUIRED_ACCOUNT_TYPE:
+ case TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_NAME:
case TAG_ATTR_RESTRICTED_ACCOUNT_TYPE:
case TAG_ATTR_TARGET_ACTIVITY:
case TAG_ATTR_TARGET_NAME:
case TAG_ATTR_TARGET_PROCESSES:
case TAG_ATTR_TASK_AFFINITY:
case TAG_ATTR_WRITE_PERMISSION:
- return 1024;
+ case TAG_ATTR_VERSION_NAME:
+ return MAX_ATTR_LEN_NAME;
case TAG_ATTR_PATH:
case TAG_ATTR_PATH_ADVANCED_PATTERN:
case TAG_ATTR_PATH_PATTERN:
case TAG_ATTR_PATH_PREFIX:
case TAG_ATTR_PATH_SUFFIX:
- case TAG_ATTR_VERSION_NAME:
- return 4000;
+ return MAX_ATTR_LEN_PATH;
+ case TAG_ATTR_VALUE:
+ return MAX_ATTR_LEN_DATA_VALUE;
+ case TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_VALUE:
+ return PROP_VALUE_MAX;
default:
return DEFAULT_MAX_STRING_ATTR_LENGTH;
}
}
- private static int getResStringMaxLength(@StyleableRes int index) {
+ private int getResStrMaxLen(@StyleableRes int index) {
+ switch (mTag) {
+ case TAG_ACTION:
+ return getActionResStrMaxLen(index);
+ case TAG_ACTIVITY:
+ return getActivityResStrMaxLen(index);
+ case TAG_ACTIVITY_ALIAS:
+ return getActivityAliasResStrMaxLen(index);
+ case TAG_APPLICATION:
+ return getApplicationResStrMaxLen(index);
+ case TAG_DATA:
+ return getDataResStrMaxLen(index);
+ case TAG_CATEGORY:
+ return getCategoryResStrMaxLen(index);
+ case TAG_GRANT_URI_PERMISSION:
+ return getGrantUriPermissionResStrMaxLen(index);
+ case TAG_INSTRUMENTATION:
+ return getInstrumentationResStrMaxLen(index);
+ case TAG_MANIFEST:
+ return getManifestResStrMaxLen(index);
+ case TAG_META_DATA:
+ return getMetaDataResStrMaxLen(index);
+ case TAG_OVERLAY:
+ return getOverlayResStrMaxLen(index);
+ case TAG_PATH_PERMISSION:
+ return getPathPermissionResStrMaxLen(index);
+ case TAG_PERMISSION:
+ return getPermissionResStrMaxLen(index);
+ case TAG_PERMISSION_GROUP:
+ return getPermissionGroupResStrMaxLen(index);
+ case TAG_PERMISSION_TREE:
+ return getPermissionTreeResStrMaxLen(index);
+ case TAG_PROPERTY:
+ return getPropertyResStrMaxLen(index);
+ case TAG_PROVIDER:
+ return getProviderResStrMaxLen(index);
+ case TAG_RECEIVER:
+ return getReceiverResStrMaxLen(index);
+ case TAG_SERVICE:
+ return getServiceResStrMaxLen(index);
+ case TAG_USES_FEATURE:
+ return getUsesFeatureResStrMaxLen(index);
+ case TAG_USES_LIBRARY:
+ return getUsesLibraryResStrMaxLen(index);
+ case TAG_USES_NATIVE_LIBRARY:
+ return getUsesNativeLibraryResStrMaxLen(index);
+ case TAG_USES_PERMISSION:
+ case TAG_USES_PERMISSION_SDK_23:
+ case TAG_USES_PERMISSION_SDK_M:
+ return getUsesPermissionResStrMaxLen(index);
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getActionResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestAction_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getActivityResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestActivity_name:
+ case R.styleable.AndroidManifestActivity_parentActivityName:
+ case R.styleable.AndroidManifestActivity_permission:
+ case R.styleable.AndroidManifestActivity_process:
+ case R.styleable.AndroidManifestActivity_taskAffinity:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getActivityAliasResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestActivityAlias_name:
+ case R.styleable.AndroidManifestActivityAlias_permission:
+ case R.styleable.AndroidManifestActivityAlias_targetActivity:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getApplicationResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestApplication_backupAgent:
+ case R.styleable.AndroidManifestApplication_manageSpaceActivity:
+ case R.styleable.AndroidManifestApplication_name:
+ case R.styleable.AndroidManifestApplication_permission:
+ case R.styleable.AndroidManifestApplication_process:
+ case R.styleable.AndroidManifestApplication_requiredAccountType:
+ case R.styleable.AndroidManifestApplication_restrictedAccountType:
+ case R.styleable.AndroidManifestApplication_taskAffinity:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getCategoryResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestCategory_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getDataResStrMaxLen(@StyleableRes int index) {
switch (index) {
case R.styleable.AndroidManifestData_host:
case R.styleable.AndroidManifestData_port:
case R.styleable.AndroidManifestData_scheme:
- return 255;
+ return MAX_ATTR_LEN_URL_COMPONENT;
case R.styleable.AndroidManifestData_mimeType:
- return 512;
+ return MAX_ATTR_LEN_MIMETYPE;
+ case R.styleable.AndroidManifestData_path:
+ case R.styleable.AndroidManifestData_pathPattern:
+ case R.styleable.AndroidManifestData_pathPrefix:
+ case R.styleable.AndroidManifestData_pathSuffix:
+ case R.styleable.AndroidManifestData_pathAdvancedPattern:
+ return MAX_ATTR_LEN_PATH;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getGrantUriPermissionResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestGrantUriPermission_path:
+ case R.styleable.AndroidManifestGrantUriPermission_pathPattern:
+ case R.styleable.AndroidManifestGrantUriPermission_pathPrefix:
+ return MAX_ATTR_LEN_PATH;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getInstrumentationResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestInstrumentation_targetPackage:
+ return MAX_ATTR_LEN_PACKAGE;
+ case R.styleable.AndroidManifestInstrumentation_name:
+ case R.styleable.AndroidManifestInstrumentation_targetProcesses:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getManifestResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifest_sharedUserId:
+ return MAX_ATTR_LEN_PACKAGE;
+ case R.styleable.AndroidManifest_versionName:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getMetaDataResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestMetaData_name:
+ return MAX_ATTR_LEN_NAME;
+ case R.styleable.AndroidManifestMetaData_value:
+ return MAX_ATTR_LEN_DATA_VALUE;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getOverlayResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestResourceOverlay_targetPackage:
+ return MAX_ATTR_LEN_PACKAGE;
+ case R.styleable.AndroidManifestResourceOverlay_category:
+ case R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyName:
+ case R.styleable.AndroidManifestResourceOverlay_targetName:
+ return MAX_ATTR_LEN_NAME;
+ case R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue:
+ return PROP_VALUE_MAX;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getPathPermissionResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestPathPermission_permission:
+ case R.styleable.AndroidManifestPathPermission_readPermission:
+ case R.styleable.AndroidManifestPathPermission_writePermission:
+ return MAX_ATTR_LEN_NAME;
+ case R.styleable.AndroidManifestPathPermission_path:
+ case R.styleable.AndroidManifestPathPermission_pathPattern:
+ case R.styleable.AndroidManifestPathPermission_pathPrefix:
+ return MAX_ATTR_LEN_PATH;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getPermissionResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestPermission_permissionGroup:
+ return MAX_ATTR_LEN_PERMISSION_GROUP;
+ case R.styleable.AndroidManifestPermission_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getPermissionGroupResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestPermissionGroup_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getPermissionTreeResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestPermissionTree_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getPropertyResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestProperty_name:
+ return MAX_ATTR_LEN_NAME;
+ case R.styleable.AndroidManifestProperty_value:
+ return MAX_ATTR_LEN_DATA_VALUE;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getProviderResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestProvider_name:
+ case R.styleable.AndroidManifestProvider_permission:
+ case R.styleable.AndroidManifestProvider_process:
+ case R.styleable.AndroidManifestProvider_readPermission:
+ case R.styleable.AndroidManifestProvider_writePermission:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getReceiverResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestReceiver_name:
+ case R.styleable.AndroidManifestReceiver_permission:
+ case R.styleable.AndroidManifestReceiver_process:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getServiceResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestReceiver_name:
+ case R.styleable.AndroidManifestReceiver_permission:
+ case R.styleable.AndroidManifestReceiver_process:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getUsesFeatureResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestUsesFeature_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getUsesLibraryResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestUsesLibrary_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getUsesNativeLibraryResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestUsesNativeLibrary_name:
+ return MAX_ATTR_LEN_NAME;
+ default:
+ return DEFAULT_MAX_STRING_ATTR_LENGTH;
+ }
+ }
+
+ private static int getUsesPermissionResStrMaxLen(@StyleableRes int index) {
+ switch (index) {
+ case R.styleable.AndroidManifestUsesPermission_name:
+ return MAX_ATTR_LEN_NAME;
default:
return DEFAULT_MAX_STRING_ATTR_LENGTH;
}
@@ -450,31 +719,25 @@ public class Element {
return (mChildTagMask & (1 << getCounterIdx(tag))) != 0;
}
- void validateStringAttrs(@NonNull XmlPullParser attrs) throws XmlPullParserException {
- for (int i = 0; i < mStringAttrNames.length; i++) {
- String attrName = mStringAttrNames[i];
- String val = attrs.getAttributeValue(getAttrNamespace(attrName), attrName);
- if (val != null && val.length() > getAttrStringMaxLength(attrName)) {
- throw new XmlPullParserException("String length limit exceeded for "
- + "attribute " + attrName + " in " + mTag);
- }
+ void validateStrAttr(String attrName, String attrValue) {
+ if (attrValue != null && attrValue.length() > getAttrStrMaxLen(attrName)) {
+ throw new SecurityException("String length limit exceeded for attribute " + attrName
+ + " in " + mTag);
}
}
- void validateResStringAttr(@StyleableRes int index, CharSequence stringValue)
- throws XmlPullParserException {
- if (stringValue != null && stringValue.length() > getResStringMaxLength(index)) {
- throw new XmlPullParserException("String length limit exceeded for "
- + "attribute in " + mTag);
+ void validateResStrAttr(@StyleableRes int index, CharSequence stringValue) {
+ if (stringValue != null && stringValue.length() > getResStrMaxLen(index)) {
+ throw new SecurityException("String length limit exceeded for attribute in " + mTag);
}
}
- void seen(@NonNull Element element) throws XmlPullParserException {
+ void seen(@NonNull Element element) {
TagCounter counter = mTagCounters[getCounterIdx(element.mTag)];
if (counter != null) {
counter.increment();
if (!counter.isValid()) {
- throw new XmlPullParserException("The number of child " + element.mTag
+ throw new SecurityException("The number of child " + element.mTag
+ " elements exceeded the max allowed in " + this.mTag);
}
}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 2e84636202be5..48adfb907ab4d 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -1393,16 +1393,17 @@ public class TypedArray implements AutoCloseable {
private CharSequence loadStringValueAt(int index) {
final int[] data = mData;
final int cookie = data[index + STYLE_ASSET_COOKIE];
+ CharSequence value = null;
if (cookie < 0) {
if (mXml != null) {
- return mXml.getPooledString(data[index + STYLE_DATA]);
+ value = mXml.getPooledString(data[index + STYLE_DATA]);
}
- return null;
+ } else {
+ value = mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
}
- CharSequence value = mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
- if (mXml != null && mXml.mValidator != null) {
+ if (value != null && mXml != null && mXml.mValidator != null) {
try {
- mXml.mValidator.validateAttr(mXml, index, value);
+ mXml.mValidator.validateResStrAttr(mXml, index / STYLE_NUM_ENTRIES, value);
} catch (XmlPullParserException e) {
throw new RuntimeException("Failed to validate resource string: " + e.getMessage());
}
diff --git a/core/java/android/content/res/Validator.java b/core/java/android/content/res/Validator.java
index 8b5e6c61d3045..cae353b3bd5ae 100644
--- a/core/java/android/content/res/Validator.java
+++ b/core/java/android/content/res/Validator.java
@@ -16,9 +16,8 @@
package android.content.res;
-import static android.content.res.Element.TAG_MANIFEST;
-
import android.annotation.NonNull;
+import android.annotation.StyleableRes;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -55,24 +54,19 @@ public class Validator {
return;
}
if (eventType == XmlPullParser.START_TAG) {
- try {
- String tag = parser.getName();
- // only validate manifests
- if (depth == 0 && mElements.size() == 0 && !TAG_MANIFEST.equals(tag)) {
- return;
- }
+ String tag = parser.getName();
+ if (Element.shouldValidate(tag)) {
+ Element element = Element.obtain(tag);
Element parent = mElements.peek();
- if (parent == null || parent.hasChild(tag)) {
- Element element = Element.obtain(tag);
- element.validateStringAttrs(parser);
- if (parent != null) {
+ if (parent != null && parent.hasChild(tag)) {
+ try {
parent.seen(element);
+ } catch (SecurityException e) {
+ cleanUp();
+ throw e;
}
- mElements.push(element);
}
- } catch (XmlPullParserException e) {
- cleanUp();
- throw e;
+ mElements.push(element);
}
} else if (eventType == XmlPullParser.END_TAG && depth == mElements.size()) {
mElements.pop().recycle();
@@ -84,11 +78,21 @@ public class Validator {
/**
* Validates the resource string of a manifest tag attribute.
*/
- public void validateAttr(@NonNull XmlPullParser parser, int index, CharSequence stringValue)
- throws XmlPullParserException {
+ public void validateResStrAttr(@NonNull XmlPullParser parser, @StyleableRes int index,
+ CharSequence stringValue) throws XmlPullParserException {
if (parser.getDepth() > mElements.size()) {
return;
}
- mElements.peek().validateResStringAttr(index, stringValue);
+ mElements.peek().validateResStrAttr(index, stringValue);
+ }
+
+ /**
+ * Validates the string of a manifest tag attribute by name.
+ */
+ public void validateStrAttr(@NonNull XmlPullParser parser, String attrName, String attrValue) {
+ if (parser.getDepth() > mElements.size()) {
+ return;
+ }
+ mElements.peek().validateStrAttr(attrName, attrValue);
}
}
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index 3afc830fa14d3..7649b32a6c7ad 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -319,7 +319,11 @@ public final class XmlBlock implements AutoCloseable {
"Namespace=" + getAttributeNamespace(idx)
+ "Name=" + getAttributeName(idx)
+ ", Value=" + getAttributeValue(idx));
- return getAttributeValue(idx);
+ String value = getAttributeValue(idx);
+ if (mValidator != null) {
+ mValidator.validateStrAttr(this, name, value);
+ }
+ return value;
}
return null;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
index 003797066b392..8c07b6cbc894e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
@@ -18,6 +18,7 @@ package com.android.server.pm.parsing
import android.content.res.Validator
import android.os.Environment
+import android.os.SystemProperties.PROP_VALUE_MAX
import android.platform.test.annotations.Postsubmit
import com.android.internal.R
import com.android.server.pm.PackageManagerService
@@ -28,7 +29,6 @@ import org.junit.Assert.assertThrows
import org.junit.Assert.fail
import org.junit.Test
import org.xmlpull.v1.XmlPullParser
-import org.xmlpull.v1.XmlPullParserException
import org.xmlpull.v1.XmlPullParserFactory
import java.io.ByteArrayInputStream
import java.io.File
@@ -75,548 +75,370 @@ class AndroidPackageParsingValidationTest {
}
@Test
- fun parseBadManifests() {
+ fun parseManifestTag() {
val tag = "manifest"
- val prefix = ""
- val suffix = ""
- parseTagBadAttr(tag, "package", 256, )
- parseTagBadAttr(tag, "android:sharedUserId", 256)
- parseTagBadAttr(tag, "android:versionName", 4000)
- parseBadApplicationTags(100, prefix, suffix, tag)
- parseBadOverlayTags(100, prefix, suffix, tag)
- parseBadInstrumentationTags(100, prefix, suffix, tag)
- parseBadPermissionGroupTags(100, prefix, suffix, tag)
- parseBadPermissionTreeTags(100, prefix, suffix, tag)
- parseBadSupportsGlTextureTags(100, prefix, suffix, tag)
- parseBadSupportsScreensTags(100, prefix, suffix, tag)
- parseBadUsesConfigurationTags(100, prefix, suffix, tag)
- parseBadUsesPermissionSdk23Tags(100, prefix, suffix, tag)
- parseBadUsesSdkTags(100, prefix, suffix, tag)
- parseBadCompatibleScreensTags(200, prefix, suffix, tag)
- parseBadQueriesTags(200, prefix, suffix, tag)
- parseBadAttributionTags(400, prefix, suffix, tag)
- parseBadUsesFeatureTags(400, prefix, suffix, tag)
- parseBadPermissionTags(2000, prefix, suffix, tag)
- parseBadUsesPermissionTags(20000, prefix, suffix, tag)
+ validateTagAttr(tag, "package", null, 256)
+ validateTagAttr(tag, "sharedUserId", null, 256)
+ validateTagAttr(tag, "versionName", null, 1024)
+ validateTagCount("application", 100, tag)
+ validateTagCount("overlay", 100, tag)
+ validateTagCount("instrumentation", 100, tag)
+ validateTagCount("permission-group", 100, tag)
+ validateTagCount("permission-tree", 100, tag)
+ validateTagCount("supports-gl-texture", 100, tag)
+ validateTagCount("supports-screens", 100, tag)
+ validateTagCount("uses-configuration", 100, tag)
+ validateTagCount("uses-sdk", 100, tag)
+ validateTagCount("compatible-screens", 200, tag)
+ validateTagCount("queries", 200, tag)
+ validateTagCount("attribution", 400, tag)
+ validateTagCount("uses-feature", 400, tag)
+ validateTagCount("permission", 2000, tag)
+ validateTagCount("uses-permission", 20000, tag)
}
- private fun parseBadApplicationTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseApplicationTag() {
val tag = "application"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
-
- parseTagBadAttr(tag, "android:backupAgent", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:manageSpaceActivity", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:permission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:process", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:requiredAccountType", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:restrictedAccountType", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:taskAffinity", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
-
- parseBadProfileableTags(100, newPrefix, newSuffix, tag)
- parseBadUsesNativeLibraryTags(100, newPrefix, newSuffix, tag)
- parseBadReceiverTags(1000, newPrefix, newSuffix, tag)
- parseBadServiceTags(1000, newPrefix, newSuffix, tag)
- parseBadActivityAliasTags(4000, newPrefix, newSuffix, tag)
- parseBadUsesLibraryTags(4000, newPrefix, newSuffix, tag)
- parseBadProviderTags(8000, newPrefix, newSuffix, tag)
- parseBadMetaDataTags(8000, newPrefix, newSuffix, tag)
- parseBadActivityTags(40000, newPrefix, newSuffix, tag)
+ validateTagAttr(tag, "backupAgent",
+ R.styleable.AndroidManifestApplication_backupAgent, 1024)
+ validateTagAttr(tag, "manageSpaceActivity",
+ R.styleable.AndroidManifestApplication_manageSpaceActivity, 1024)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestApplication_name, 1024)
+ validateTagAttr(tag, "permission", R.styleable.AndroidManifestApplication_permission, 1024)
+ validateTagAttr(tag, "process", R.styleable.AndroidManifestApplication_process, 1024)
+ validateTagAttr(tag, "requiredAccountType",
+ R.styleable.AndroidManifestApplication_requiredAccountType, 1024)
+ validateTagAttr(tag, "restrictedAccountType",
+ R.styleable.AndroidManifestApplication_restrictedAccountType, 1024)
+ validateTagAttr(tag, "taskAffinity",
+ R.styleable.AndroidManifestApplication_taskAffinity, 1024)
+ validateTagCount("profileable", 100, tag)
+ validateTagCount("uses-native-library", 100, tag)
+ validateTagCount("receiver", 1000, tag)
+ validateTagCount("service", 1000, tag)
+ validateTagCount("meta-data", 1000, tag)
+ validateTagCount("uses-library", 1000, tag)
+ validateTagCount("activity-alias", 4000, tag)
+ validateTagCount("provider", 8000, tag)
+ validateTagCount("activity", 40000, tag)
}
- private fun parseBadProfileableTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
- val tag = "profileable"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- }
-
- private fun parseBadUsesNativeLibraryTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseUsesNativeLibraryTag() {
val tag = "uses-native-library"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestUsesNativeLibrary_name, 1024)
}
- private fun parseBadReceiverTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseReceiverTag() {
val tag = "receiver"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:permission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:process", 1024, prefix, suffix)
-
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadMetaDataTags(8000, newPrefix, newSuffix, tag)
- parseBadIntentFilterTags(20000, newPrefix, newSuffix, tag)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestReceiver_name, 1024)
+ validateTagAttr(tag, "permission", R.styleable.AndroidManifestReceiver_permission, 1024)
+ validateTagAttr(tag, "process", R.styleable.AndroidManifestReceiver_process, 1024)
+ validateTagCount("meta-data", 1000, tag)
+ validateTagCount("intent-filter", 20000, tag)
}
- private fun parseBadServiceTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseServiceTag() {
val tag = "service"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:permission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:process", 1024, prefix, suffix)
-
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadMetaDataTags(8000, newPrefix, newSuffix, tag)
- parseBadIntentFilterTags(20000, newPrefix, newSuffix, tag)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestService_name, 1024)
+ validateTagAttr(tag, "permission", R.styleable.AndroidManifestService_permission, 1024)
+ validateTagAttr(tag, "process", R.styleable.AndroidManifestService_process, 1024)
+ validateTagCount("meta-data", 1000, tag)
+ validateTagCount("intent-filter", 20000, tag)
}
- private fun parseBadActivityAliasTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseActivityAliasTag() {
val tag = "activity-alias"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:permission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:targetActivity", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadMetaDataTags(8000, newPrefix, newSuffix, tag)
- parseBadIntentFilterTags(20000, newPrefix, newSuffix, tag)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestActivityAlias_name, 1024)
+ validateTagAttr(tag, "permission",
+ R.styleable.AndroidManifestActivityAlias_permission, 1024)
+ validateTagAttr(tag, "targetActivity",
+ R.styleable.AndroidManifestActivityAlias_targetActivity, 1024)
+ validateTagCount("meta-data", 1000, tag)
+ validateTagCount("intent-filter", 20000, tag)
}
- private fun parseBadUsesLibraryTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseUsesLibraryTag() {
val tag = "uses-library"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestUsesLibrary_name, 1024)
}
- private fun parseBadActivityTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseActivityTag() {
val tag = "activity"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:parentActivityName", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:permission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:process", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:taskAffinity", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadLayoutTags(1000, newPrefix, newSuffix, tag)
- parseBadMetaDataTags(8000, newPrefix, newSuffix, tag)
- parseBadIntentFilterTags(20000, newPrefix, newSuffix, tag)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestActivity_name, 1024)
+ validateTagAttr(tag, "parentActivityName",
+ R.styleable.AndroidManifestActivity_parentActivityName, 1024)
+ validateTagAttr(tag, "permission", R.styleable.AndroidManifestActivity_permission, 1024)
+ validateTagAttr(tag, "process", R.styleable.AndroidManifestActivity_process, 1024)
+ validateTagAttr(tag, "taskAffinity", R.styleable.AndroidManifestActivity_taskAffinity, 1024)
+ validateTagCount("layout", 1000, tag)
+ validateTagCount("meta-data", 1000, tag)
+ validateTagCount("intent-filter", 20000, tag)
}
- private fun parseBadLayoutTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
- val tag = "layout"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- }
-
- private fun parseBadOverlayTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseOverlayTag() {
val tag = "overlay"
- parseTagBadAttr(tag, "android:category", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:requiredSystemPropertyName", 32768, prefix, suffix)
- parseTagBadAttr(tag, "android:requiredSystemPropertyValue", 256, prefix, suffix)
- parseTagBadAttr(tag, "android:targetPackage", 256, prefix, suffix)
- parseTagBadAttr(tag, "android:targetName", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "category", R.styleable.AndroidManifestResourceOverlay_category, 1024)
+ validateTagAttr(tag, "requiredSystemPropertyName",
+ R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyName, 1024)
+ validateTagAttr(tag, "requiredSystemPropertyValue",
+ R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue, PROP_VALUE_MAX)
+ validateTagAttr(tag, "targetPackage",
+ R.styleable.AndroidManifestResourceOverlay_targetPackage, 256)
+ validateTagAttr(tag, "targetName",
+ R.styleable.AndroidManifestResourceOverlay_targetName, 1024)
}
- private fun parseBadInstrumentationTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseInstrumentationTag() {
val tag = "instrumentation"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:targetPackage", 256, prefix, suffix)
- parseTagBadAttr(tag, "android:targetProcesses", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestInstrumentation_name, 1024)
+ validateTagAttr(tag, "targetPackage",
+ R.styleable.AndroidManifestInstrumentation_targetPackage, 256)
+ validateTagAttr(tag, "targetProcesses",
+ R.styleable.AndroidManifestInstrumentation_targetProcesses, 1024)
}
- private fun parseBadPermissionGroupTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parsePermissionGroupTag() {
val tag = "permission-group"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestPermissionGroup_name, 1024)
}
- private fun parseBadPermissionTreeTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parsePermissionTreeTag() {
val tag = "permission-tree"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestPermissionTree_name, 1024)
}
- private fun parseBadSupportsGlTextureTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseSupportsGlTextureTag() {
val tag = "supports-gl-texture"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", null, 1024)
}
- private fun parseBadSupportsScreensTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
- val tag = "supports-screens"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- }
-
- private fun parseBadUsesConfigurationTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
- val tag = "uses-configuration"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- }
-
- private fun parseBadUsesPermissionSdk23Tags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseUsesPermissionSdk23Tag() {
val tag = "uses-permission-sdk-23"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestUsesPermission_name, 1024)
}
- private fun parseBadUsesSdkTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
- val tag = "uses-sdk"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- }
-
- private fun parseBadCompatibleScreensTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseCompatibleScreensTag() {
val tag = "compatible-screens"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadScreenTags(4000, newPrefix, newSuffix, tag)
+ validateTagCount("screen", 4000, tag)
}
- private fun parseBadScreenTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
- val tag = "screen"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- }
-
- private fun parseBadQueriesTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseQueriesTag() {
val tag = "queries"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadPackageTags(1000, newPrefix, newSuffix, tag)
- parseBadIntentTags(2000, newPrefix, newSuffix, tag)
- parseBadProviderTags(8000, newPrefix, newSuffix, tag)
+ validateTagCount("package", 1000, tag)
+ validateTagCount("intent", 2000, tag)
+ validateTagCount("provider", 8000, tag)
}
- private fun parseBadPackageTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parsePackageTag() {
val tag = "package"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", null, 1024)
}
- private fun parseBadIntentTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseIntentTag() {
val tag = "intent"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadActionTags(20000, newPrefix, newSuffix, tag)
- parseBadCategoryTags(40000, newPrefix, newSuffix, tag)
- parseBadDataTags(40000, newPrefix, newSuffix, tag)
+ validateTagCount("action", 20000, tag)
+ validateTagCount("category", 40000, tag)
+ validateTagCount("data", 40000, tag)
}
- private fun parseBadProviderTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseProviderTag() {
val tag = "provider"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:permission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:process", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:readPermission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:writePermission", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadGrantUriPermissionTags(100, newPrefix, newSuffix, tag)
- parseBadPathPermissionTags(100, newPrefix, newSuffix, tag)
- parseBadMetaDataTags(8000, newPrefix, newSuffix, tag)
- parseBadIntentFilterTags(20000, newPrefix, newSuffix, tag)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestProvider_name, 1024)
+ validateTagAttr(tag, "permission", R.styleable.AndroidManifestProvider_permission, 1024)
+ validateTagAttr(tag, "process", R.styleable.AndroidManifestProvider_process, 1024)
+ validateTagAttr(tag, "readPermission",
+ R.styleable.AndroidManifestProvider_readPermission, 1024)
+ validateTagAttr(tag, "writePermission",
+ R.styleable.AndroidManifestProvider_writePermission, 1024)
+ validateTagCount("grant-uri-permission", 100, tag)
+ validateTagCount("path-permission", 100, tag)
+ validateTagCount("meta-data", 1000, tag)
+ validateTagCount("intent-filter", 20000, tag)
}
- private fun parseBadGrantUriPermissionTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseGrantUriPermissionTag() {
val tag = "grant-uri-permission"
- parseTagBadAttr(tag, "android:path", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathPrefix", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathPattern", 4000, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "path", R.styleable.AndroidManifestGrantUriPermission_path, 4000)
+ validateTagAttr(tag, "pathPrefix",
+ R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 4000)
+ validateTagAttr(tag, "pathPattern",
+ R.styleable.AndroidManifestGrantUriPermission_pathPattern, 4000)
}
- private fun parseBadPathPermissionTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parsePathPermissionTag() {
val tag = "path-permission"
- parseTagBadAttr(tag, "android:path", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathPrefix", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathPattern", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:permission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:readPermission", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:writePermission", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "path", R.styleable.AndroidManifestPathPermission_path, 4000)
+ validateTagAttr(tag, "pathPrefix",
+ R.styleable.AndroidManifestPathPermission_pathPrefix, 4000)
+ validateTagAttr(tag, "pathPattern",
+ R.styleable.AndroidManifestPathPermission_pathPattern, 4000)
+ validateTagAttr(tag, "permission",
+ R.styleable.AndroidManifestPathPermission_permission, 1024)
+ validateTagAttr(tag, "readPermission",
+ R.styleable.AndroidManifestPathPermission_readPermission, 1024)
+ validateTagAttr(tag, "writePermission",
+ R.styleable.AndroidManifestPathPermission_writePermission, 1024)
}
- private fun parseBadMetaDataTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseMetaDataTag() {
val tag = "meta-data"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:value", 32768, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestMetaData_name, 1024)
+ validateTagAttr(tag, "value", R.styleable.AndroidManifestMetaData_value, 4000)
}
- private fun parseBadIntentFilterTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseIntentFilterTag() {
val tag = "intent-filter"
- val newPrefix = "$prefix<$tag>"
- val newSuffix = "$tag>$suffix"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- parseBadActionTags(20000, newPrefix, newSuffix, tag)
- parseBadCategoryTags(40000, newPrefix, newSuffix, tag)
- parseBadDataTags(40000, newPrefix, newSuffix, tag)
+ validateTagCount("action", 20000, tag)
+ validateTagCount("category", 40000, tag)
+ validateTagCount("data", 40000, tag)
}
- private fun parseBadActionTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseActionTag() {
val tag = "action"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestAction_name, 1024)
}
- private fun parseBadCategoryTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseCategoryTag() {
val tag = "category"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestCategory_name, 1024)
}
- private fun parseBadDataTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseDataTag() {
val tag = "data"
- parseTagBadAttr(tag, "android:scheme", 256, prefix, suffix)
- parseTagBadAttr(tag, "android:host", 256, prefix, suffix)
- parseTagBadAttr(tag, "android:path", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathPattern", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathPrefix", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathSuffix", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:pathAdvancedPattern", 4000, prefix, suffix)
- parseTagBadAttr(tag, "android:mimeType", 512, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "scheme", R.styleable.AndroidManifestData_scheme, 256)
+ validateTagAttr(tag, "host", R.styleable.AndroidManifestData_host, 256)
+ validateTagAttr(tag, "path", R.styleable.AndroidManifestData_path, 4000)
+ validateTagAttr(tag, "pathPattern", R.styleable.AndroidManifestData_pathPattern, 4000)
+ validateTagAttr(tag, "pathPrefix", R.styleable.AndroidManifestData_pathPrefix, 4000)
+ validateTagAttr(tag, "pathSuffix", R.styleable.AndroidManifestData_pathSuffix, 4000)
+ validateTagAttr(tag, "pathAdvancedPattern",
+ R.styleable.AndroidManifestData_pathAdvancedPattern, 4000)
+ validateTagAttr(tag, "mimeType", R.styleable.AndroidManifestData_mimeType, 512)
}
- private fun parseBadAttributionTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
- val tag = "attribution"
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
- }
-
- private fun parseBadUsesFeatureTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseUsesFeatureTag() {
val tag = "uses-feature"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestUsesFeature_name, 1024)
}
- private fun parseBadPermissionTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parsePermissionTag() {
val tag = "permission"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseTagBadAttr(tag, "android:permissionGroup", 256, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestPermission_name, 1024)
+ validateTagAttr(tag, "permissionGroup",
+ R.styleable.AndroidManifestPermission_permissionGroup, 256)
}
- private fun parseBadUsesPermissionTags(
- maxNum: Int,
- prefix: String,
- suffix: String,
- parentTag: String
- ) {
+ @Test
+ fun parseUsesPermissionTag() {
val tag = "uses-permission"
- parseTagBadAttr(tag, "android:name", 1024, prefix, suffix)
- parseBadTagCount(tag, maxNum, parentTag, prefix, suffix)
+ validateTagAttr(tag, "name", R.styleable.AndroidManifestUsesPermission_name, 1024)
}
- private fun parseTagBadAttr(
- tag: String,
- attrName: String,
- maxLength: Int,
- prefix: String = "",
- suffix: String = ""
+ private fun validateTagAttr(tag: String, name: String, index: Int?, maxLen: Int) {
+ validateTagAttr_shouldPass(tag, name, index, maxLen)
+ validateTagAttr_shouldFail(tag, name, index, maxLen)
+ }
+
+ private fun validateTagAttr_shouldPass(
+ tag: String,
+ name: String,
+ index: Int?,
+ maxLen: Int
) {
- var attrValue = "x".repeat(maxLength)
- var tagValue = if (tag.equals("manifest")) "$tag $ns" else tag
- var manifestStr = "$prefix<$tagValue $attrName=\"$attrValue\" />$suffix"
+ val value = "x".repeat(maxLen)
+ val xml = "<$tag $name=\"$value\" />"
+ pullParser.setInput(ByteArrayInputStream(xml.toByteArray()), null)
+ val validator = Validator()
+ pullParser.nextTag()
+ validator.validate(pullParser)
try {
- parseManifestStr(manifestStr)
- } catch (e: XmlPullParserException) {
- fail("Failed to parse valid <$tag> attribute $attrName with max length of $maxLength:" +
+ validator.validateStrAttr(pullParser, name, value)
+ } catch (e: SecurityException) {
+ fail("Failed to parse valid <$tag> attribute $name with max length of $maxLen:" +
" ${e.message}")
}
- attrValue = "x".repeat(maxLength + 1)
- manifestStr = "$prefix<$tagValue $attrName=\"$attrValue\" />$suffix"
- val e = assertThrows(XmlPullParserException::class.java) {
- parseManifestStr(manifestStr)
+ if (index != null) {
+ try {
+ validator.validateResStrAttr(pullParser, index, value)
+ } catch (e: SecurityException) {
+ fail("Failed to parse valid <$tag> resource string attribute $name with max" +
+ " length of $maxLen: ${e.message}")
+ }
}
- assertEquals(expectedAttrLengthErrorMsg(attrName.split(":").last(), tag), e.message)
}
- private fun parseBadTagCount(
- tag: String,
- maxNum: Int,
- parentTag: String,
- prefix: String,
- suffix: String
+ private fun validateTagAttr_shouldFail(
+ tag: String,
+ name: String,
+ index: Int?,
+ maxLen: Int
) {
- var tags = "<$tag />".repeat(maxNum)
- var manifestStr = "$prefix$tags$suffix"
+ val value = "x".repeat(maxLen + 1)
+ val xml = "<$tag $name=\"$value\" />"
+ pullParser.setInput(ByteArrayInputStream(xml.toByteArray()), null)
+ val validator = Validator()
+ pullParser.nextTag()
+ validator.validate(pullParser)
+ val e1 = assertThrows(SecurityException::class.java) {
+ validator.validateStrAttr(pullParser, name, value)
+ }
+ assertEquals(expectedAttrLengthErrorMsg(name, tag), e1.message)
+ if (index != null) {
+ val e2 = assertThrows(SecurityException::class.java) {
+ validator.validateResStrAttr(pullParser, index, value)
+ }
+ assertEquals(expectedResAttrLengthErrorMsg(tag), e2.message)
+ }
+ }
+
+ private fun validateTagCount(tag: String, maxNum: Int, parentTag: String) {
+ validateTagCount_shouldPass(tag, maxNum, parentTag)
+ validateTagCount_shouldFail(tag, maxNum, parentTag)
+ }
+
+ private fun validateTagCount_shouldPass(tag: String, maxNum: Int, parentTag: String) {
+ val tags = "<$tag />".repeat(maxNum)
+ val xml = "<$parentTag>$tags$parentTag>"
try {
- parseManifestStr(manifestStr)
- } catch (e: XmlPullParserException) {
+ parseXmlStr(xml)
+ } catch (e: SecurityException) {
fail("Failed to parse <$tag> with max count limit of $maxNum under" +
" <$parentTag>: ${e.message}")
}
- tags = "<$tag />".repeat(maxNum + 1)
- manifestStr = "$prefix$tags$suffix"
- val e = assertThrows(XmlPullParserException::class.java) {
- parseManifestStr(manifestStr)
+ }
+
+ private fun validateTagCount_shouldFail(tag: String, maxNum: Int, parentTag: String) {
+ val tags = "<$tag />".repeat(maxNum + 1)
+ val xml = "<$parentTag>$tags$parentTag>"
+ val e = assertThrows(SecurityException::class.java) {
+ parseXmlStr(xml)
}
assertEquals(expectedCountErrorMsg(tag, parentTag), e.message)
}
@@ -624,13 +446,12 @@ class AndroidPackageParsingValidationTest {
@Test
fun parseUnexpectedTag_shouldSkip() {
val host = "x".repeat(256)
- val dataTags = "".repeat(2049)
- val ns = "http://schemas.android.com/apk/res/android"
- val manifestStr = "$dataTags"
- parseManifestStr(manifestStr)
+ val dataTags = "".repeat(2049)
+ val xml = "$dataTags"
+ parseXmlStr(xml)
}
- fun parseManifestStr(manifestStr: String) {
+ fun parseXmlStr(manifestStr: String) {
pullParser.setInput(ByteArrayInputStream(manifestStr.toByteArray()), null)
val validator = Validator()
do {
@@ -647,39 +468,4 @@ class AndroidPackageParsingValidationTest {
fun expectedResAttrLengthErrorMsg(tag: String) =
"String length limit exceeded for attribute in $tag"
-
- @Test
- fun validateResAttrs() {
- pullParser.setInput(ByteArrayInputStream("".toByteArray()), null)
- pullParser.next()
- val validator = Validator()
- validator.validate(pullParser)
- validateResAttr(pullParser, validator, R.styleable.AndroidManifestData_host,
- "R.styleable.AndroidManifestData_host", 255)
- validateResAttr(pullParser, validator, R.styleable.AndroidManifestData_port,
- "R.styleable.AndroidManifestData_port", 255)
- validateResAttr(pullParser, validator, R.styleable.AndroidManifestData_scheme,
- "R.styleable.AndroidManifestData_scheme", 255)
- validateResAttr(pullParser, validator, R.styleable.AndroidManifestData_mimeType,
- "R.styleable.AndroidManifestData_mimeType", 512)
- }
-
- fun validateResAttr(
- parser: XmlPullParser,
- validator: Validator,
- resId: Int,
- resIdStr: String,
- maxLength: Int
- ) {
- try {
- validator.validateAttr(parser, resId, "x".repeat(maxLength))
- } catch (e: XmlPullParserException) {
- fail("Failed to parse valid string resource attribute $resIdStr with max length of" +
- " $maxLength: ${e.message}")
- }
- val e = assertThrows(XmlPullParserException::class.java) {
- validator.validateAttr(parser, resId, "x".repeat(maxLength + 1))
- }
- assertEquals(expectedResAttrLengthErrorMsg("manifest"), e.message)
- }
-}
\ No newline at end of file
+}