Eliminate redundant attribute reads in validation
The validator was reading all string attributes in addition to the attribute reads in PackageParsing. Eliminating the attribute reads from the validator and instead validating at the time when attributes are read in PackageParser further reduces the performance regression to ~5%. The mean times measured on a lynx devices are: PackageParsingPerfTest#sequentialNoCache[v1]_new_ns: 748223578 PackageParsingPerfTest#sequentialNoCache[v1]_old_ns: 790309363 PackageParsingPerfTest#sequentialNoCache[v1]_none_ns: 717520130 Bug: 289190523, 267185315 Test: atest PackageParsingPerfTest Test: atest AndroidPackageParsingValidationTest Change-Id: I53e3606a48fd97b2e27e41f34bb83029ab908807
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = "<manifest $ns>"
|
||||
val suffix = "</manifest>"
|
||||
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 = "<data android:host=\"$host\" />".repeat(2049)
|
||||
val ns = "http://schemas.android.com/apk/res/android"
|
||||
val manifestStr = "<manifest xmlns:android=\"$ns\" package=\"test\">$dataTags</manifest>"
|
||||
parseManifestStr(manifestStr)
|
||||
val dataTags = "<data host=\"$host\" />".repeat(2049)
|
||||
val xml = "<manifest package=\"test\">$dataTags</manifest>"
|
||||
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("<manifest />".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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user