17ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski/* 27ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Copyright (C) 2016 The Android Open Source Project 37ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * 47ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 57ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * you may not use this file except in compliance with the License. 67ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * You may obtain a copy of the License at 77ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * 87ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 97ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * 107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Unless required by applicable law or agreed to in writing, software 117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * See the License for the specific language governing permissions and 147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * limitations under the License. 157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski */ 167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#define ATRACE_TAG ATRACE_TAG_RESOURCES 187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "androidfw/LoadedArsc.h" 207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include <cstddef> 227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include <limits> 237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "android-base/logging.h" 257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "android-base/stringprintf.h" 267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "utils/ByteOrder.h" 277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "utils/Trace.h" 287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#ifdef _WIN32 307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#ifdef ERROR 317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#undef ERROR 327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#endif 337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#endif 347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "androidfw/ByteBucketArray.h" 36da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski#include "androidfw/Chunk.h" 37929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski#include "androidfw/ResourceUtils.h" 387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "androidfw/Util.h" 397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiusing android::base::StringPrintf; 417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskinamespace android { 437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 44da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiconstexpr const static int kAppPackageId = 0x7f; 457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// Element of a TypeSpec array. See TypeSpec. 477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistruct Type { 487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The configuration for which this type defines entries. 497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // This is already converted to host endianness. 507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ResTable_config configuration; 517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Pointer to the mmapped data where entry definitions are kept. 537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_type* type; 547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}; 557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// TypeSpec is going to be immediately proceeded by 577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// an array of Type structs, all in the same block of memory. 587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistruct TypeSpec { 597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Pointer to the mmapped data where flags are kept. 607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Flags denote whether the resource entry is public 617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // and under which configurations it varies. 627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_typeSpec* type_spec; 637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The number of types that follow this struct. 657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There is a type for each configuration 667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // that entries are defined for. 677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t type_count; 687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Trick to easily access a variable number of Type structs 707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // proceeding this struct, and to ensure their alignment. 717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Type types[0]; 727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}; 737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// TypeSpecPtr points to the block of memory that holds 757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// a TypeSpec struct, followed by an array of Type structs. 767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// TypeSpecPtr is a managed pointer that knows how to delete 777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// itself. 787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiusing TypeSpecPtr = util::unique_cptr<TypeSpec>; 797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 80da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskinamespace { 81da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// Builder that helps accumulate Type structs and then create a single 837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// contiguous block of memory to store both the TypeSpec struct and 847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// the Type structs. 857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiclass TypeSpecPtrBuilder { 867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski public: 877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtrBuilder(const ResTable_typeSpec* header) : header_(header) {} 887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski void AddType(const ResTable_type* type) { 907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ResTable_config config; 917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski config.copyFromDtoH(type->config); 927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_.push_back(Type{config, type}); 937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtr Build() { 967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check for overflow. 977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(Type) < types_.size()) { 987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return {}; 997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpec* type_spec = (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(Type))); 1017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski type_spec->type_spec = header_; 1027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski type_spec->type_count = types_.size(); 1037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(Type)); 1047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return TypeSpecPtr(type_spec); 1057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski private: 1087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski DISALLOW_COPY_AND_ASSIGN(TypeSpecPtrBuilder); 1097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_typeSpec* header_; 1117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski std::vector<Type> types_; 1127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}; 1137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} // namespace 1157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 116da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskibool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config, 117da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LoadedArscEntry* out_entry, ResTable_config* out_selected_config, 1187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint32_t* out_flags) const { 119da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski ATRACE_CALL(); 120c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski 121c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski // If the type IDs are offset in this package, we need to take that into account when searching 122c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski // for a type. 123c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_]; 1247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (ptr == nullptr) { 1257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Don't bother checking if the entry ID is larger than 1297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // the number of entries. 130da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (entry_idx >= dtohl(ptr->type_spec->entryCount)) { 1317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_config* best_config = nullptr; 1357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_type* best_type = nullptr; 1367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint32_t best_offset = 0; 1377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (uint32_t i = 0; i < ptr->type_count; i++) { 1397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Type* type = &ptr->types[i]; 1407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type->configuration.match(config) && 1427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski (best_config == nullptr || type->configuration.isBetterThan(*best_config, &config))) { 1437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The configuration matches and is better than the previous selection. 1447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Find the entry value if it exists for this configuration. 1457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t entry_count = dtohl(type->type->entryCount); 146da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (entry_idx < entry_count) { 1477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>( 1487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize)); 149da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const uint32_t offset = dtohl(entry_offsets[entry_idx]); 1507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset != ResTable_type::NO_ENTRY) { 1517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There is an entry for this resource, record it. 1527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski best_config = &type->configuration; 1537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski best_type = type->type; 1547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski best_offset = offset + dtohl(type->type->entriesStart); 1557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (best_type == nullptr) { 1617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint32_t* flags = reinterpret_cast<const uint32_t*>(ptr->type_spec + 1); 165da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski *out_flags = dtohl(flags[entry_idx]); 1667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *out_selected_config = *best_config; 1677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_entry* best_entry = reinterpret_cast<const ResTable_entry*>( 1697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(best_type) + best_offset); 1707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_entry->entry = best_entry; 1717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_entry->type_string_ref = StringPoolRef(&type_string_pool_, best_type->id - 1); 1727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_entry->entry_string_ref = StringPoolRef(&key_string_pool_, dtohl(best_entry->key.index)); 1737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return true; 1747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 1757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// The destructor gets generated into arbitrary translation units 1777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// if left implicit, which causes the compiler to complain about 1787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// forward declarations and incomplete types. 1797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam LesinskiLoadedArsc::~LoadedArsc() {} 1807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 181da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskibool LoadedArsc::FindEntry(uint32_t resid, const ResTable_config& config, 182da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LoadedArscEntry* out_entry, ResTable_config* out_selected_config, 183da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski uint32_t* out_flags) const { 184da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski ATRACE_CALL(); 185929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const uint8_t package_id = get_package_id(resid); 186929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const uint8_t type_id = get_type_id(resid); 187929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const uint16_t entry_id = get_entry_id(resid); 1887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_id == 0) { 1907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Invalid ID 0x" << std::hex << resid << std::dec << "."; 1917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (const auto& loaded_package : packages_) { 1957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (loaded_package->package_id_ == package_id) { 1967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return loaded_package->FindEntry(type_id - 1, entry_id, config, out_entry, 1977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_selected_config, out_flags); 1987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 2027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 203da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiconst LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const { 204929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const uint8_t package_id = get_package_id(resid); 2057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (const auto& loaded_package : packages_) { 2067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (loaded_package->package_id_ == package_id) { 207da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return loaded_package.get(); 2087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return nullptr; 2117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 2127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistatic bool VerifyType(const Chunk& chunk) { 2147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 215136fd0764faf7a588b4a1b479d7a8cc6fe18fcc6Adam Lesinski const ResTable_type* header = chunk.header<ResTable_type, kResTableTypeMinSize>(); 2167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entry_count = dtohl(header->entryCount); 2187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_count > std::numeric_limits<uint16_t>::max()) { 2197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many entries in RES_TABLE_TYPE_TYPE."; 2207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Make sure that there is enough room for the entry offsets. 2247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t offsets_offset = chunk.header_size(); 2257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entries_offset = dtohl(header->entriesStart); 2267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t offsets_length = sizeof(uint32_t) * entry_count; 2277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offsets_offset + offsets_length > entries_offset) { 2297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offsets overlap actual entry data."; 2307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entries_offset > chunk.size()) { 2347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offsets extend beyond chunk."; 2357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entries_offset & 0x03) { 2397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entries start at unaligned address."; 2407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check each entry offset. 2447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint32_t* offsets = 2457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint32_t*>(reinterpret_cast<const uint8_t*>(header) + offsets_offset); 2467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (size_t i = 0; i < entry_count; i++) { 2477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint32_t offset = dtohl(offsets[i]); 2487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset != ResTable_type::NO_ENTRY) { 2497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check that the offset is aligned. 2507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset & 0x03) { 2517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offset at index " << i << " is not 4-byte aligned."; 2527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check that the offset doesn't overflow. 2567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset > std::numeric_limits<uint32_t>::max() - entries_offset) { 2577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Overflow in offset. 2587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offset at index " << i << " is too large."; 2597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski offset += entries_offset; 2637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset > chunk.size() - sizeof(ResTable_entry)) { 2647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offset at index " << i << " is too large. No room for ResTable_entry."; 2657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>( 2697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(header) + offset); 2707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entry_size = dtohs(entry->size); 2717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_size < sizeof(*entry)) { 2727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "ResTable_entry size " << entry_size << " is too small."; 2737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check the declared entrySize. 2777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_size > chunk.size() || offset > chunk.size() - entry_size) { 2787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "ResTable_entry size " << entry_size << " is too large."; 2797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // If this is a map entry, then keep validating. 2837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_size >= sizeof(ResTable_map_entry)) { 2847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(entry); 2857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t map_entry_count = dtohl(map->count); 2867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t map_entries_start = offset + entry_size; 2887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (map_entries_start & 0x03) { 2897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Map entries start at unaligned offset."; 2907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Each entry is sizeof(ResTable_map) big. 2947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (map_entry_count > ((chunk.size() - map_entries_start) / sizeof(ResTable_map))) { 2957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many map entries in ResTable_map_entry."; 2967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Great, all the map entries fit!. 3007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else { 3017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There needs to be room for one Res_value struct. 3027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset + entry_size > chunk.size() - sizeof(Res_value)) { 3037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "No room for Res_value after ResTable_entry."; 3047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 3057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Res_value* value = reinterpret_cast<const Res_value*>( 3087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(entry) + entry_size); 3097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t value_size = dtohs(value->size); 3107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (value_size < sizeof(Res_value)) { 3117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Res_value is too small."; 3127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 3137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (value_size > chunk.size() || offset + entry_size > chunk.size() - value_size) { 3167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Res_value size is too large."; 3177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 3187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return true; 3237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 3247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3250c40524953f3d36a880f91183302a2ea5c722930Adam Lesinskivoid LoadedPackage::CollectConfigurations(bool exclude_mipmap, 3260c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski std::set<ResTable_config>* out_configs) const { 3270c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const static std::u16string kMipMap = u"mipmap"; 3280c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const size_t type_count = type_specs_.size(); 3290c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski for (size_t i = 0; i < type_count; i++) { 3300c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i]; 3310c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (type_spec != nullptr) { 3320c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (exclude_mipmap) { 3330c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const int type_idx = type_spec->type_spec->id - 1; 3340c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski size_t type_name_len; 3350c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const char16_t* type_name16 = type_string_pool_.stringAt(type_idx, &type_name_len); 3360c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (type_name16 != nullptr) { 3370c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (kMipMap.compare(0, std::u16string::npos, type_name16, type_name_len) == 0) { 3380c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski // This is a mipmap type, skip collection. 3390c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski continue; 3400c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3410c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3420c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const char* type_name = type_string_pool_.string8At(type_idx, &type_name_len); 3430c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (type_name != nullptr) { 3440c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (strncmp(type_name, "mipmap", type_name_len) == 0) { 3450c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski // This is a mipmap type, skip collection. 3460c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski continue; 3470c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3480c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3490c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3500c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski 3510c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski for (size_t j = 0; j < type_spec->type_count; j++) { 3520c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski out_configs->insert(type_spec->types[j].configuration); 3530c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3540c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3550c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3560c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski} 3570c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski 3580c40524953f3d36a880f91183302a2ea5c722930Adam Lesinskivoid LoadedPackage::CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const { 3590c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski char temp_locale[RESTABLE_MAX_LOCALE_LEN]; 3600c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const size_t type_count = type_specs_.size(); 3610c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski for (size_t i = 0; i < type_count; i++) { 3620c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i]; 3630c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (type_spec != nullptr) { 3640c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski for (size_t j = 0; j < type_spec->type_count; j++) { 3650c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski const ResTable_config& configuration = type_spec->types[j].configuration; 3660c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski if (configuration.locale != 0) { 3670c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski configuration.getBcp47Locale(temp_locale, canonicalize); 3680c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski std::string locale(temp_locale); 3690c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski out_locales->insert(std::move(locale)); 3700c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3710c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3720c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3730c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski } 3740c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski} 3750c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski 376929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinskiuint32_t LoadedPackage::FindEntryByName(const std::u16string& type_name, 377929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const std::u16string& entry_name) const { 378929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski ssize_t type_idx = type_string_pool_.indexOfString(type_name.data(), type_name.size()); 379929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski if (type_idx < 0) { 380929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski return 0u; 381929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski } 382929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski 383929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski ssize_t key_idx = key_string_pool_.indexOfString(entry_name.data(), entry_name.size()); 384929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski if (key_idx < 0) { 385929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski return 0u; 386929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski } 387929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski 388929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const TypeSpec* type_spec = type_specs_[type_idx].get(); 389929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski if (type_spec == nullptr) { 390929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski return 0u; 391929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski } 392929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski 393929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski for (size_t ti = 0; ti < type_spec->type_count; ti++) { 394929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const Type* type = &type_spec->types[ti]; 395929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski size_t entry_count = dtohl(type->type->entryCount); 396929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski for (size_t entry_idx = 0; entry_idx < entry_count; entry_idx++) { 397929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>( 398929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize)); 399929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const uint32_t offset = dtohl(entry_offsets[entry_idx]); 400929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski if (offset != ResTable_type::NO_ENTRY) { 401929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski const ResTable_entry* entry = 402929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type->type) + 403929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski dtohl(type->type->entriesStart) + offset); 404929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski if (dtohl(entry->key.index) == static_cast<uint32_t>(key_idx)) { 405929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski // The package ID will be overridden by the caller (due to runtime assignment of package 406929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski // IDs for shared libraries). 407929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski return make_resid(0x00, type_idx + type_id_offset_ + 1, entry_idx); 408929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski } 409929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski } 410929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski } 411929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski } 412929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski return 0u; 413929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski} 414929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski 415da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskistd::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { 4167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 417da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski std::unique_ptr<LoadedPackage> loaded_package{new LoadedPackage()}; 418da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 41933af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski constexpr size_t kMinPackageSize = 42033af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski sizeof(ResTable_package) - sizeof(ResTable_package::typeIdOffset); 42133af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski const ResTable_package* header = chunk.header<ResTable_package, kMinPackageSize>(); 4227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (header == nullptr) { 4237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_PACKAGE_TYPE is too small."; 424da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski loaded_package->package_id_ = dtohl(header->id); 428da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (loaded_package->package_id_ == 0) { 429da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski // Package ID of 0 means this is a shared library. 430da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_ = true; 431da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 432da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 433c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski if (header->header.headerSize >= sizeof(ResTable_package)) { 434c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski uint32_t type_id_offset = dtohl(header->typeIdOffset); 435c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski if (type_id_offset > std::numeric_limits<uint8_t>::max()) { 436c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski LOG(ERROR) << "Type ID offset in RES_TABLE_PACKAGE_TYPE is too large."; 437c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski return {}; 438c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski } 439c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski loaded_package->type_id_offset_ = static_cast<int>(type_id_offset); 440c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski } 441c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski 442da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), 443da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski &loaded_package->package_name_); 4447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // A TypeSpec builder. We use this to accumulate the set of Types 4467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // available for a TypeSpec, and later build a single, contiguous block 4477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // of memory that holds all the Types together with the TypeSpec. 4487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski std::unique_ptr<TypeSpecPtrBuilder> types_builder; 4497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Keep track of the last seen type index. Since type IDs are 1-based, 4517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // this records their index, which is 0-based (type ID - 1). 4527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint8_t last_type_idx = 0; 4537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); 4557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski while (iter.HasNext()) { 4567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Chunk child_chunk = iter.Next(); 4577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski switch (child_chunk.type()) { 4587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_STRING_POOL_TYPE: { 4597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uintptr_t pool_address = 4607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<uintptr_t>(child_chunk.header<ResChunk_header>()); 4617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uintptr_t header_address = reinterpret_cast<uintptr_t>(header); 4627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (pool_address == header_address + dtohl(header->typeStrings)) { 4637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // This string pool is the type string pool. 4647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski status_t err = loaded_package->type_string_pool_.setTo( 4657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski child_chunk.header<ResStringPool_header>(), child_chunk.size()); 4667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (err != NO_ERROR) { 4677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Corrupt package type string pool."; 468da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else if (pool_address == header_address + dtohl(header->keyStrings)) { 4717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // This string pool is the key string pool. 4727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski status_t err = loaded_package->key_string_pool_.setTo( 4737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski child_chunk.header<ResStringPool_header>(), child_chunk.size()); 4747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (err != NO_ERROR) { 4757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Corrupt package key string pool."; 476da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else { 4797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << "Too many string pool chunks found in package."; 4807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 4827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_TYPE_SPEC_TYPE: { 4847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_NAME("LoadTableTypeSpec"); 4857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Starting a new TypeSpec, so finish the old one if there was one. 4877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (types_builder) { 4887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtr type_spec_ptr = types_builder->Build(); 4897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec_ptr == nullptr) { 4907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many type configurations, overflow detected."; 491da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); 4947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_builder = {}; 4967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski last_type_idx = 0; 4977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>(); 5007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec == nullptr) { 5017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE is too small."; 502da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec->id == 0) { 5067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has invalid ID 0."; 507da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 510c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski if (loaded_package->type_id_offset_ + static_cast<int>(type_spec->id) > 511c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski std::numeric_limits<uint8_t>::max()) { 512c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has out of range ID."; 513c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski return {}; 514c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski } 515c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski 5167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The data portion of this chunk contains entry_count 32bit entries, 5177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // each one representing a set of flags. 5187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Here we only validate that the chunk is well formed. 5197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entry_count = dtohl(type_spec->entryCount); 5207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There can only be 2^16 entries in a type, because that is the ID 5227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // space for entries (EEEE) in the resource ID 0xPPTTEEEE. 5237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_count > std::numeric_limits<uint16_t>::max()) { 5247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many entries in RES_TABLE_TYPE_SPEC_TYPE: " << entry_count << "."; 525da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_count * sizeof(uint32_t) > chunk.data_size()) { 5297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk too small to hold entries in RES_TABLE_TYPE_SPEC_TYPE."; 530da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski last_type_idx = type_spec->id - 1; 5347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec); 5357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 5367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_TYPE_TYPE: { 538136fd0764faf7a588b4a1b479d7a8cc6fe18fcc6Adam Lesinski const ResTable_type* type = child_chunk.header<ResTable_type, kResTableTypeMinSize>(); 5397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type == nullptr) { 5407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE is too small."; 541da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type->id == 0) { 5457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE has invalid ID 0."; 546da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Type chunks must be preceded by their TypeSpec chunks. 5507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (!types_builder || type->id - 1 != last_type_idx) { 5517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Found RES_TABLE_TYPE_TYPE chunk without " 5527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski "RES_TABLE_TYPE_SPEC_TYPE."; 553da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (!VerifyType(child_chunk)) { 557da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_builder->AddType(type); 5617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 5627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 563da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski case RES_TABLE_LIBRARY_TYPE: { 564da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const ResTable_lib_header* lib = child_chunk.header<ResTable_lib_header>(); 565da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (lib == nullptr) { 566da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_LIBRARY_TYPE is too small."; 567da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 568da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 569da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 570da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (child_chunk.data_size() / sizeof(ResTable_lib_entry) < dtohl(lib->count)) { 571da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LOG(ERROR) << "Chunk too small to hold entries in RES_TABLE_LIBRARY_TYPE."; 572da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 573da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 574da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 575da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_package_map_.reserve(dtohl(lib->count)); 576da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 577da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const ResTable_lib_entry* const entry_begin = 578da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski reinterpret_cast<const ResTable_lib_entry*>(child_chunk.data_ptr()); 579da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const ResTable_lib_entry* const entry_end = entry_begin + dtohl(lib->count); 580da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski for (auto entry_iter = entry_begin; entry_iter != entry_end; ++entry_iter) { 581da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski std::string package_name; 582da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski util::ReadUtf16StringFromDevice(entry_iter->packageName, 583da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski arraysize(entry_iter->packageName), &package_name); 584da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 585da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) { 586da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LOG(ERROR) << base::StringPrintf( 587da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.", 588da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski dtohl(entry_iter->packageId), package_name.c_str()); 589da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 590da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 591da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 592da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_package_map_.emplace_back(std::move(package_name), 593da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski dtohl(entry_iter->packageId)); 594da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 595da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 596da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } break; 597da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 5987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski default: 5997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); 6007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 6017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Finish the last TypeSpec. 6057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (types_builder) { 6067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtr type_spec_ptr = types_builder->Build(); 6077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec_ptr == nullptr) { 6087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many type configurations, overflow detected."; 609da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 6107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); 6127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (iter.HadError()) { 6157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << iter.GetLastError(); 616da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 6177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 618da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return loaded_package; 6197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 6207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 621da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskibool LoadedArsc::LoadTable(const Chunk& chunk, bool load_as_shared_library) { 6227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 6237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_header* header = chunk.header<ResTable_header>(); 6247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (header == nullptr) { 6257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE is too small."; 6267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 6277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t package_count = dtohl(header->packageCount); 6307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t packages_seen = 0; 6317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski packages_.reserve(package_count); 6337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); 6357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski while (iter.HasNext()) { 6367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Chunk child_chunk = iter.Next(); 6377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski switch (child_chunk.type()) { 6387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_STRING_POOL_TYPE: 6397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Only use the first string pool. Ignore others. 6407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (global_string_pool_.getError() == NO_INIT) { 6417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski status_t err = global_string_pool_.setTo(child_chunk.header<ResStringPool_header>(), 6427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski child_chunk.size()); 6437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (err != NO_ERROR) { 6447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Corrupt string pool."; 6457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 6467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else { 6487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << "Multiple string pool chunks found in resource table."; 6497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 6517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_PACKAGE_TYPE: { 6537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (packages_seen + 1 > package_count) { 6547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "More package chunks were found than the " << package_count 6557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski << " declared in the " 6567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski "header."; 6577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 6587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski packages_seen++; 6607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 661da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski std::unique_ptr<LoadedPackage> loaded_package = LoadedPackage::Load(child_chunk); 662da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (!loaded_package) { 6637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 6647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 665da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 666da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski // Mark the package as dynamic if we are forcefully loading the Apk as a shared library. 667da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (loaded_package->package_id_ == kAppPackageId) { 668da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_ = load_as_shared_library; 669da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 6700c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski loaded_package->system_ = system_; 6717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski packages_.push_back(std::move(loaded_package)); 6727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 6737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski default: 6757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); 6767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 6777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (iter.HadError()) { 6817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << iter.GetLastError(); 6827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 6837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return true; 6857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 6867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6870c40524953f3d36a880f91183302a2ea5c722930Adam Lesinskistd::unique_ptr<const LoadedArsc> LoadedArsc::Load(const void* data, size_t len, bool system, 6880c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski bool load_as_shared_library) { 6897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 6907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Not using make_unique because the constructor is private. 6927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc()); 6930c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski loaded_arsc->system_ = system; 6947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ChunkIterator iter(data, len); 6967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski while (iter.HasNext()) { 6977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Chunk chunk = iter.Next(); 6987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski switch (chunk.type()) { 6997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_TYPE: 700da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (!loaded_arsc->LoadTable(chunk, load_as_shared_library)) { 7017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return {}; 7027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 7037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 7047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 7057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski default: 7067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); 7077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 7087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 7097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 7107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 7117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (iter.HadError()) { 7127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << iter.GetLastError(); 7137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return {}; 7147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 7150c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski 7160c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski // Need to force a move for mingw32. 7170c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski return std::move(loaded_arsc); 7187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 7197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 7207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} // namespace android 721