/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.res; import static android.os.SystemProperties.PROP_VALUE_MAX; import android.annotation.NonNull; import android.util.Pools.SimplePool; import android.util.Slog; import androidx.annotation.StyleableRes; import com.android.internal.R; import java.util.Set; /** * Defines the string attribute length and child tag count restrictions for a xml element. * * {@hide} */ 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 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; /** * The mime type max length restriction here should match the restriction that is also * placed in {@link android.content.pm.PackageManager#setMimeGroup(String, Set)} */ private static final int MAX_ATTR_LEN_MIMETYPE = 255; private static final int MAX_ATTR_LEN_NAME = 1024; private static final int MAX_ATTR_LEN_PATH = 4000; private static final int MAX_ATTR_LEN_VALUE = 32_768; private static final int MAX_TOTAL_META_DATA_SIZE = 262_144; private static final String BAD_COMPONENT_NAME_CHARS = ";,[](){}:?%^*|/\\"; private static final String TAG = "PackageParsing"; protected static final String TAG_ACTION = "action"; protected static final String TAG_ACTIVITY = "activity"; protected static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions"; protected static final String TAG_ACTIVITY_ALIAS = "activity-alias"; protected static final String TAG_APPLICATION = "application"; protected static final String TAG_ATTRIBUTION = "attribution"; protected static final String TAG_CATEGORY = "category"; protected static final String TAG_COMPATIBLE_SCREENS = "compatible-screens"; protected static final String TAG_DATA = "data"; protected static final String TAG_EAT_COMMENT = "eat-comment"; protected static final String TAG_FEATURE_GROUP = "feature-group"; protected static final String TAG_GRANT_URI_PERMISSION = "grant-uri-permission"; protected static final String TAG_INSTRUMENTATION = "instrumentation"; protected static final String TAG_INTENT = "intent"; protected static final String TAG_INTENT_FILTER = "intent-filter"; protected static final String TAG_KEY_SETS = "key-sets"; protected static final String TAG_LAYOUT = "layout"; protected static final String TAG_MANIFEST = "manifest"; protected static final String TAG_META_DATA = "meta-data"; protected static final String TAG_ORIGINAL_PACKAGE = "original-package"; protected static final String TAG_OVERLAY = "overlay"; protected static final String TAG_PACKAGE = "package"; protected static final String TAG_PACKAGE_VERIFIER = "package-verifier"; protected static final String TAG_PATH_PERMISSION = "path-permission"; protected static final String TAG_PERMISSION = "permission"; protected static final String TAG_PERMISSION_GROUP = "permission-group"; protected static final String TAG_PERMISSION_TREE = "permission-tree"; protected static final String TAG_PROFILEABLE = "profileable"; protected static final String TAG_PROTECTED_BROADCAST = "protected-broadcast"; protected static final String TAG_PROPERTY = "property"; protected static final String TAG_PROVIDER = "provider"; protected static final String TAG_QUERIES = "queries"; protected static final String TAG_RECEIVER = "receiver"; protected static final String TAG_RESTRICT_UPDATE = "restrict-update"; protected static final String TAG_SCREEN = "screen"; protected static final String TAG_SERVICE = "service"; protected static final String TAG_SUPPORT_SCREENS = "supports-screens"; protected static final String TAG_SUPPORTS_GL_TEXTURE = "supports-gl-texture"; protected static final String TAG_SUPPORTS_INPUT = "supports-input"; protected static final String TAG_SUPPORTS_SCREENS = "supports-screens"; protected static final String TAG_URI_RELATIVE_FILTER_GROUP = "uri-relative-filter-group"; protected static final String TAG_USES_CONFIGURATION = "uses-configuration"; protected static final String TAG_USES_FEATURE = "uses-feature"; protected static final String TAG_USES_GL_TEXTURE = "uses-gl-texture"; protected static final String TAG_USES_LIBRARY = "uses-library"; protected static final String TAG_USES_NATIVE_LIBRARY = "uses-native-library"; protected static final String TAG_USES_PERMISSION = "uses-permission"; protected static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23"; protected static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m"; protected static final String TAG_USES_SDK = "uses-sdk"; protected static final String TAG_USES_SPLIT = "uses-split"; protected static final String TAG_ATTR_BACKUP_AGENT = "backupAgent"; protected static final String TAG_ATTR_CATEGORY = "category"; protected static final String TAG_ATTR_FRAGMENT = "fragment"; protected static final String TAG_ATTR_FRAGMENT_ADVANCED_PATTERN = "fragmentAdvancedPattern"; protected static final String TAG_ATTR_FRAGMENT_PATTERN = "fragmentPattern"; protected static final String TAG_ATTR_FRAGMENT_PREFIX = "fragmentPrefix"; protected static final String TAG_ATTR_FRAGMENT_SUFFIX = "fragmentSuffix"; protected static final String TAG_ATTR_HOST = "host"; protected static final String TAG_ATTR_MANAGE_SPACE_ACTIVITY = "manageSpaceActivity"; protected static final String TAG_ATTR_MIMETYPE = "mimeType"; protected static final String TAG_ATTR_MIMEGROUP = "mimeGroup"; protected static final String TAG_ATTR_NAME = "name"; protected static final String TAG_ATTR_PACKAGE = "package"; protected static final String TAG_ATTR_PATH = "path"; protected static final String TAG_ATTR_PATH_ADVANCED_PATTERN = "pathAdvancedPattern"; protected static final String TAG_ATTR_PATH_PATTERN = "pathPattern"; protected static final String TAG_ATTR_PATH_PREFIX = "pathPrefix"; protected static final String TAG_ATTR_PATH_SUFFIX = "pathSuffix"; protected static final String TAG_ATTR_PARENT_ACTIVITY_NAME = "parentActivityName"; protected static final String TAG_ATTR_PERMISSION = "permission"; protected static final String TAG_ATTR_PERMISSION_GROUP = "permissionGroup"; protected static final String TAG_ATTR_PORT = "port"; protected static final String TAG_ATTR_PROCESS = "process"; protected static final String TAG_ATTR_QUERY = "query"; protected static final String TAG_ATTR_QUERY_ADVANCED_PATTERN = "queryAdvancedPattern"; protected static final String TAG_ATTR_QUERY_PATTERN = "queryPattern"; protected static final String TAG_ATTR_QUERY_PREFIX = "queryPrefix"; protected static final String TAG_ATTR_QUERY_SUFFIX = "querySuffix"; protected static final String TAG_ATTR_READ_PERMISSION = "readPermission"; protected static final String TAG_ATTR_REQUIRED_ACCOUNT_TYPE = "requiredAccountType"; protected static final String TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_NAME = "requiredSystemPropertyName"; protected static final String TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_VALUE = "requiredSystemPropertyValue"; protected static final String TAG_ATTR_RESTRICTED_ACCOUNT_TYPE = "restrictedAccountType"; protected static final String TAG_ATTR_SCHEME = "scheme"; protected static final String TAG_ATTR_SHARED_USER_ID = "sharedUserId"; protected static final String TAG_ATTR_TARGET_ACTIVITY = "targetActivity"; protected static final String TAG_ATTR_TARGET_NAME = "targetName"; protected static final String TAG_ATTR_TARGET_PACKAGE = "targetPackage"; protected static final String TAG_ATTR_TARGET_PROCESSES = "targetProcesses"; protected static final String TAG_ATTR_TASK_AFFINITY = "taskAffinity"; protected static final String TAG_ATTR_VALUE = "value"; protected static final String TAG_ATTR_VERSION_NAME = "versionName"; protected static final String TAG_ATTR_WRITE_PERMISSION = "writePermission"; protected static final String TAG_ATTR_ZYGOTE_PRELOAD_NAME = "zygotePreloadName"; // 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]; String mTag; private static final ThreadLocal> sPool = ThreadLocal.withInitial(() -> new SimplePool<>(MAX_POOL_SIZE)); @NonNull static Element obtain(@NonNull String tag) { Element element = sPool.get().acquire(); if (element == null) { element = new Element(); } element.init(tag); return element; } void recycle() { mTag = null; sPool.get().release(this); } private long mChildTagMask = 0; private int mTotalComponentMetadataSize = 0; private static int getCounterIdx(String tag) { switch(tag) { case TAG_LAYOUT: return 0; case TAG_META_DATA: return 1; case TAG_INTENT_FILTER: return 2; case TAG_PROFILEABLE: return 3; case TAG_USES_NATIVE_LIBRARY: return 4; case TAG_RECEIVER: return 5; case TAG_SERVICE: return 6; case TAG_ACTIVITY_ALIAS: return 7; case TAG_USES_LIBRARY: return 8; case TAG_PROVIDER: return 9; case TAG_ACTIVITY: return 10; case TAG_ACTION: return 11; case TAG_CATEGORY: return 12; case TAG_DATA: return 13; case TAG_APPLICATION: return 14; case TAG_OVERLAY: return 15; case TAG_INSTRUMENTATION: return 16; case TAG_PERMISSION_GROUP: return 17; case TAG_PERMISSION_TREE: return 18; case TAG_SUPPORTS_GL_TEXTURE: return 19; case TAG_SUPPORTS_SCREENS: return 20; case TAG_USES_CONFIGURATION: return 21; case TAG_USES_SDK: return 22; case TAG_COMPATIBLE_SCREENS: return 23; case TAG_QUERIES: return 24; case TAG_ATTRIBUTION: return 25; case TAG_USES_FEATURE: return 26; case TAG_PERMISSION: return 27; case TAG_USES_PERMISSION: case TAG_USES_PERMISSION_SDK_23: case TAG_USES_PERMISSION_SDK_M: return 28; case TAG_GRANT_URI_PERMISSION: return 29; case TAG_PATH_PERMISSION: return 30; case TAG_PACKAGE: return 31; case TAG_INTENT: return 32; case TAG_URI_RELATIVE_FILTER_GROUP: return 33; default: // The size of the mTagCounters array should be equal to this value+1 return 34; } } 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_URI_RELATIVE_FILTER_GROUP: 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; } } private void init(String tag) { this.mTag = tag; mChildTagMask = 0; mTotalComponentMetadataSize = 0; switch (tag) { case TAG_ACTIVITY: initializeCounter(TAG_LAYOUT, 1000); initializeCounter(TAG_META_DATA, 1000); initializeCounter(TAG_INTENT_FILTER, 20000); break; case TAG_ACTIVITY_ALIAS: case TAG_RECEIVER: case TAG_SERVICE: initializeCounter(TAG_META_DATA, 1000); initializeCounter(TAG_INTENT_FILTER, 20000); break; case TAG_APPLICATION: 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_PROVIDER, 8000); initializeCounter(TAG_ACTIVITY, 30000); break; case TAG_COMPATIBLE_SCREENS: initializeCounter(TAG_SCREEN, 4000); break; case TAG_INTENT: case TAG_INTENT_FILTER: initializeCounter(TAG_URI_RELATIVE_FILTER_GROUP, 100); initializeCounter(TAG_ACTION, 20000); initializeCounter(TAG_CATEGORY, 40000); initializeCounter(TAG_DATA, 40000); break; case TAG_MANIFEST: initializeCounter(TAG_APPLICATION, 100); initializeCounter(TAG_OVERLAY, 100); initializeCounter(TAG_INSTRUMENTATION, 100); initializeCounter(TAG_PERMISSION_GROUP, 100); initializeCounter(TAG_PERMISSION_TREE, 100); initializeCounter(TAG_SUPPORTS_GL_TEXTURE, 100); initializeCounter(TAG_SUPPORTS_SCREENS, 100); initializeCounter(TAG_USES_CONFIGURATION, 100); initializeCounter(TAG_USES_SDK, 100); initializeCounter(TAG_COMPATIBLE_SCREENS, 200); initializeCounter(TAG_QUERIES, 200); initializeCounter(TAG_ATTRIBUTION, 400); initializeCounter(TAG_USES_FEATURE, 400); initializeCounter(TAG_PERMISSION, 2000); initializeCounter(TAG_USES_PERMISSION, 20000); break; case TAG_PROVIDER: initializeCounter(TAG_GRANT_URI_PERMISSION, 100); initializeCounter(TAG_PATH_PERMISSION, 100); initializeCounter(TAG_META_DATA, 1000); initializeCounter(TAG_INTENT_FILTER, 20000); break; case TAG_QUERIES: initializeCounter(TAG_PACKAGE, 1000); initializeCounter(TAG_INTENT, 2000); initializeCounter(TAG_PROVIDER, 8000); break; case TAG_URI_RELATIVE_FILTER_GROUP: initializeCounter(TAG_DATA, 100); break; } } private static int getAttrStrMaxLen(String attrName) { switch (attrName) { case TAG_ATTR_HOST: case TAG_ATTR_PORT: 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 MAX_ATTR_LEN_PACKAGE; case TAG_ATTR_MIMETYPE: return MAX_ATTR_LEN_MIMETYPE; case TAG_ATTR_BACKUP_AGENT: case TAG_ATTR_CATEGORY: case TAG_ATTR_MANAGE_SPACE_ACTIVITY: case TAG_ATTR_MIMEGROUP: case TAG_ATTR_NAME: case TAG_ATTR_PARENT_ACTIVITY_NAME: case TAG_ATTR_PERMISSION: 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: case TAG_ATTR_VERSION_NAME: case TAG_ATTR_ZYGOTE_PRELOAD_NAME: return MAX_ATTR_LEN_NAME; case TAG_ATTR_FRAGMENT: case TAG_ATTR_FRAGMENT_ADVANCED_PATTERN: case TAG_ATTR_FRAGMENT_PATTERN: case TAG_ATTR_FRAGMENT_PREFIX: case TAG_ATTR_FRAGMENT_SUFFIX: 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_QUERY: case TAG_ATTR_QUERY_ADVANCED_PATTERN: case TAG_ATTR_QUERY_PATTERN: case TAG_ATTR_QUERY_PREFIX: case TAG_ATTR_QUERY_SUFFIX: return MAX_ATTR_LEN_PATH; case TAG_ATTR_VALUE: return MAX_ATTR_LEN_VALUE; case TAG_ATTR_REQUIRED_SYSTEM_PROPERTY_VALUE: return PROP_VALUE_MAX; default: return DEFAULT_MAX_STRING_ATTR_LENGTH; } } 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: case R.styleable.AndroidManifestApplication_zygotePreloadName: 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 MAX_ATTR_LEN_URL_COMPONENT; case R.styleable.AndroidManifestData_mimeType: return MAX_ATTR_LEN_MIMETYPE; case R.styleable.AndroidManifestData_mimeGroup: return MAX_ATTR_LEN_NAME; 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: case R.styleable.AndroidManifestData_query: case R.styleable.AndroidManifestData_queryPattern: case R.styleable.AndroidManifestData_queryPrefix: case R.styleable.AndroidManifestData_querySuffix: case R.styleable.AndroidManifestData_queryAdvancedPattern: case R.styleable.AndroidManifestData_fragment: case R.styleable.AndroidManifestData_fragmentPattern: case R.styleable.AndroidManifestData_fragmentPrefix: case R.styleable.AndroidManifestData_fragmentSuffix: case R.styleable.AndroidManifestData_fragmentAdvancedPattern: 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_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_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; } } private void initializeCounter(String tag, int max) { int idx = getCounterIdx(tag); if (mTagCounters[idx] == null) { mTagCounters[idx] = new TagCounter(); } mTagCounters[idx].reset(max); mChildTagMask |= 1 << idx; } private boolean isComponentNameAttr(String name) { switch (mTag) { case TAG_ACTIVITY: switch (name) { case TAG_ATTR_NAME: case TAG_ATTR_PARENT_ACTIVITY_NAME: return true; default: return false; } case TAG_ACTIVITY_ALIAS: switch (name) { case TAG_ATTR_TARGET_ACTIVITY: return true; default: return false; } case TAG_APPLICATION: switch (name) { case TAG_ATTR_BACKUP_AGENT: case TAG_ATTR_NAME: case TAG_ATTR_ZYGOTE_PRELOAD_NAME: return true; default: return false; } case TAG_INSTRUMENTATION: case TAG_PROVIDER: case TAG_RECEIVER: case TAG_SERVICE: switch (name) { case TAG_ATTR_NAME: return true; default: return false; } default: return false; } } private boolean isComponentNameAttr(@StyleableRes int index) { switch (mTag) { case TAG_ACTIVITY: return index == R.styleable.AndroidManifestActivity_name || index == R.styleable.AndroidManifestActivity_parentActivityName; case TAG_ACTIVITY_ALIAS: return index == R.styleable.AndroidManifestActivityAlias_targetActivity; case TAG_APPLICATION: return index == R.styleable.AndroidManifestApplication_backupAgent || index == R.styleable.AndroidManifestApplication_name || index == R.styleable.AndroidManifestApplication_zygotePreloadName; case TAG_INSTRUMENTATION: return index == R.styleable.AndroidManifestInstrumentation_name; case TAG_PROVIDER: return index == R.styleable.AndroidManifestProvider_name; case TAG_RECEIVER: return index == R.styleable.AndroidManifestReceiver_name; case TAG_SERVICE: return index == R.styleable.AndroidManifestService_name; default: return false; } } boolean hasChild(String tag) { return (mChildTagMask & (1 << getCounterIdx(tag))) != 0; } void validateComponentName(CharSequence name) { boolean isStart = true; for (int i = 0; i < name.length(); i++) { if (BAD_COMPONENT_NAME_CHARS.indexOf(name.charAt(i)) >= 0) { Slog.e(TAG, name + " is not a valid Java class name"); throw new SecurityException(name + " is not a valid Java class name"); } } } 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); } if (isComponentNameAttr(attrName)) { validateComponentName(attrValue); } } 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); } if (isComponentNameAttr(index)) { validateComponentName(stringValue); } } void validateComponentMetadata(String value) { mTotalComponentMetadataSize += value.length(); if (mTotalComponentMetadataSize > MAX_TOTAL_META_DATA_SIZE) { throw new SecurityException("Max total meta data size limit exceeded for " + mTag); } } void seen(@NonNull Element element) { TagCounter counter = mTagCounters[getCounterIdx(element.mTag)]; if (counter != null) { counter.increment(); if (!counter.isValid()) { throw new SecurityException("The number of child " + element.mTag + " elements exceeded the max allowed in " + this.mTag); } } } }