Merge "Eliminate redundant attribute reads in validation" into main
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