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