1f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski/* 2f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * Copyright (C) 2014 The Android Open Source Project 3f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * 4f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * you may not use this file except in compliance with the License. 6f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * You may obtain a copy of the License at 7f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * 8f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * 10f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * Unless required by applicable law or agreed to in writing, software 11f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * See the License for the specific language governing permissions and 14f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski * limitations under the License. 15f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski */ 16f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 17f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski#include <androidfw/TypeWrappers.h> 18f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 19c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski#include <algorithm> 20c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 21f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinskinamespace android { 22f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 23c8f71aa67ea599cb80205496cb67e9e7a121299cAdam LesinskiTypeVariant::TypeVariant(const ResTable_type* data) : data(data), mLength(dtohl(data->entryCount)) { 24c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (data->flags & ResTable_type::FLAG_SPARSE) { 25c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const uint32_t entryCount = dtohl(data->entryCount); 26c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const uintptr_t containerEnd = reinterpret_cast<uintptr_t>(data) + dtohl(data->header.size); 27c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const uint32_t* const entryIndices = reinterpret_cast<const uint32_t*>( 28c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski reinterpret_cast<uintptr_t>(data) + dtohs(data->header.headerSize)); 29c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (reinterpret_cast<uintptr_t>(entryIndices) + (sizeof(uint32_t) * entryCount) 30c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski > containerEnd) { 31c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ALOGE("Type's entry indices extend beyond its boundaries"); 32c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski mLength = 0; 33c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } else { 34c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski mLength = ResTable_sparseTypeEntry{entryIndices[entryCount - 1]}.idx + 1; 35c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 36c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 37c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski} 38c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 39f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam LesinskiTypeVariant::iterator& TypeVariant::iterator::operator++() { 40f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski mIndex++; 41c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (mIndex > mTypeVariant->mLength) { 42c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski mIndex = mTypeVariant->mLength; 43f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } 44f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return *this; 45f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski} 46f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 47c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinskistatic bool keyCompare(uint32_t entry, uint16_t index) { 48c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski return dtohs(ResTable_sparseTypeEntry{entry}.idx) < index; 49c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski} 50c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 51f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinskiconst ResTable_entry* TypeVariant::iterator::operator*() const { 52f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski const ResTable_type* type = mTypeVariant->data; 53c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (mIndex >= mTypeVariant->mLength) { 54f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return NULL; 55f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } 56f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 57c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const uint32_t entryCount = dtohl(mTypeVariant->data->entryCount); 58f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski const uintptr_t containerEnd = reinterpret_cast<uintptr_t>(type) 59f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski + dtohl(type->header.size); 60f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski const uint32_t* const entryIndices = reinterpret_cast<const uint32_t*>( 61f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski reinterpret_cast<uintptr_t>(type) + dtohs(type->header.headerSize)); 62f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski if (reinterpret_cast<uintptr_t>(entryIndices) + (sizeof(uint32_t) * entryCount) > containerEnd) { 63f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski ALOGE("Type's entry indices extend beyond its boundaries"); 64f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return NULL; 65f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } 66f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 67c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski uint32_t entryOffset; 68c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (type->flags & ResTable_type::FLAG_SPARSE) { 69c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski auto iter = std::lower_bound(entryIndices, entryIndices + entryCount, mIndex, keyCompare); 70c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (iter == entryIndices + entryCount 71c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski || dtohs(ResTable_sparseTypeEntry{*iter}.idx) != mIndex) { 72c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski return NULL; 73c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 74c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 75c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski entryOffset = static_cast<uint32_t>(dtohs(ResTable_sparseTypeEntry{*iter}.offset)) * 4u; 76c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } else { 77c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski entryOffset = dtohl(entryIndices[mIndex]); 78c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 79c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 80f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski if (entryOffset == ResTable_type::NO_ENTRY) { 81f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return NULL; 82f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } 83f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 84f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski if ((entryOffset & 0x3) != 0) { 85fb600d60c06192f1a5b1c09bc86f92a80894a6c1Adam Lesinski ALOGE("Index %u points to entry with unaligned offset 0x%08x", mIndex, entryOffset); 86f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return NULL; 87f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } 88f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 89f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>( 90f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski reinterpret_cast<uintptr_t>(type) + dtohl(type->entriesStart) + entryOffset); 91f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski if (reinterpret_cast<uintptr_t>(entry) > containerEnd - sizeof(*entry)) { 92f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski ALOGE("Entry offset at index %u points outside the Type's boundaries", mIndex); 93f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return NULL; 94f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } else if (reinterpret_cast<uintptr_t>(entry) + dtohs(entry->size) > containerEnd) { 95f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski ALOGE("Entry at index %u extends beyond Type's boundaries", mIndex); 96f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return NULL; 97f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } else if (dtohs(entry->size) < sizeof(*entry)) { 98f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski ALOGE("Entry at index %u is too small (%u)", mIndex, dtohs(entry->size)); 99f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return NULL; 100f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } 101f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski return entry; 102f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski} 103f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 104f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski} // namespace android 105