LoadedArsc.cpp revision c6aada9c5789b2777b19c522d3cd5052bbe784a4
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" 377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "androidfw/Util.h" 387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiusing android::base::StringPrintf; 407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskinamespace android { 427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 43da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiconstexpr const static int kAppPackageId = 0x7f; 447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// Element of a TypeSpec array. See TypeSpec. 467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistruct Type { 477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The configuration for which this type defines entries. 487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // This is already converted to host endianness. 497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ResTable_config configuration; 507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Pointer to the mmapped data where entry definitions are kept. 527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_type* type; 537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}; 547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// TypeSpec is going to be immediately proceeded by 567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// an array of Type structs, all in the same block of memory. 577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistruct TypeSpec { 587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Pointer to the mmapped data where flags are kept. 597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Flags denote whether the resource entry is public 607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // and under which configurations it varies. 617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_typeSpec* type_spec; 627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The number of types that follow this struct. 647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There is a type for each configuration 657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // that entries are defined for. 667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t type_count; 677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Trick to easily access a variable number of Type structs 697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // proceeding this struct, and to ensure their alignment. 707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Type types[0]; 717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}; 727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// TypeSpecPtr points to the block of memory that holds 747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// a TypeSpec struct, followed by an array of Type structs. 757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// TypeSpecPtr is a managed pointer that knows how to delete 767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// itself. 777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiusing TypeSpecPtr = util::unique_cptr<TypeSpec>; 787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 79da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskinamespace { 80da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// Builder that helps accumulate Type structs and then create a single 827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// contiguous block of memory to store both the TypeSpec struct and 837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// the Type structs. 847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiclass TypeSpecPtrBuilder { 857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski public: 867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtrBuilder(const ResTable_typeSpec* header) : header_(header) {} 877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski void AddType(const ResTable_type* type) { 897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ResTable_config config; 907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski config.copyFromDtoH(type->config); 917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_.push_back(Type{config, type}); 927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtr Build() { 957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check for overflow. 967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(Type) < types_.size()) { 977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return {}; 987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpec* type_spec = (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(Type))); 1007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski type_spec->type_spec = header_; 1017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski type_spec->type_count = types_.size(); 1027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(Type)); 1037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return TypeSpecPtr(type_spec); 1047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski private: 1077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski DISALLOW_COPY_AND_ASSIGN(TypeSpecPtrBuilder); 1087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_typeSpec* header_; 1107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski std::vector<Type> types_; 1117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}; 1127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} // namespace 1147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 115da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskibool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config, 116da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LoadedArscEntry* out_entry, ResTable_config* out_selected_config, 1177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint32_t* out_flags) const { 118da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski ATRACE_CALL(); 119c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski 120c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski // If the type IDs are offset in this package, we need to take that into account when searching 121c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski // for a type. 122c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_]; 1237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (ptr == nullptr) { 1247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Don't bother checking if the entry ID is larger than 1287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // the number of entries. 129da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (entry_idx >= dtohl(ptr->type_spec->entryCount)) { 1307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_config* best_config = nullptr; 1347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_type* best_type = nullptr; 1357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint32_t best_offset = 0; 1367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (uint32_t i = 0; i < ptr->type_count; i++) { 1387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Type* type = &ptr->types[i]; 1397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type->configuration.match(config) && 1417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski (best_config == nullptr || type->configuration.isBetterThan(*best_config, &config))) { 1427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The configuration matches and is better than the previous selection. 1437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Find the entry value if it exists for this configuration. 1447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t entry_count = dtohl(type->type->entryCount); 145da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (entry_idx < entry_count) { 1467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>( 1477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize)); 148da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const uint32_t offset = dtohl(entry_offsets[entry_idx]); 1497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset != ResTable_type::NO_ENTRY) { 1507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There is an entry for this resource, record it. 1517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski best_config = &type->configuration; 1527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski best_type = type->type; 1537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski best_offset = offset + dtohl(type->type->entriesStart); 1547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (best_type == nullptr) { 1607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint32_t* flags = reinterpret_cast<const uint32_t*>(ptr->type_spec + 1); 164da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski *out_flags = dtohl(flags[entry_idx]); 1657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *out_selected_config = *best_config; 1667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_entry* best_entry = reinterpret_cast<const ResTable_entry*>( 1687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(best_type) + best_offset); 1697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_entry->entry = best_entry; 1707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_entry->type_string_ref = StringPoolRef(&type_string_pool_, best_type->id - 1); 1717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_entry->entry_string_ref = StringPoolRef(&key_string_pool_, dtohl(best_entry->key.index)); 1727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return true; 1737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 1747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// The destructor gets generated into arbitrary translation units 1767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// if left implicit, which causes the compiler to complain about 1777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// forward declarations and incomplete types. 1787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam LesinskiLoadedArsc::~LoadedArsc() {} 1797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 180da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskibool LoadedArsc::FindEntry(uint32_t resid, const ResTable_config& config, 181da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LoadedArscEntry* out_entry, ResTable_config* out_selected_config, 182da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski uint32_t* out_flags) const { 183da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski ATRACE_CALL(); 1847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint8_t package_id = util::get_package_id(resid); 1857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint8_t type_id = util::get_type_id(resid); 1867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint16_t entry_id = util::get_entry_id(resid); 1877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_id == 0) { 1897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Invalid ID 0x" << std::hex << resid << std::dec << "."; 1907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 1917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 1937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (const auto& loaded_package : packages_) { 1947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (loaded_package->package_id_ == package_id) { 1957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return loaded_package->FindEntry(type_id - 1, entry_id, config, out_entry, 1967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski out_selected_config, out_flags); 1977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 1997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 2017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 202da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiconst LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const { 2037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint8_t package_id = util::get_package_id(resid); 2047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (const auto& loaded_package : packages_) { 2057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (loaded_package->package_id_ == package_id) { 206da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return loaded_package.get(); 2077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return nullptr; 2107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 2117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistatic bool VerifyType(const Chunk& chunk) { 2137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 2147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_type* header = chunk.header<ResTable_type>(); 2157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entry_count = dtohl(header->entryCount); 2177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_count > std::numeric_limits<uint16_t>::max()) { 2187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many entries in RES_TABLE_TYPE_TYPE."; 2197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Make sure that there is enough room for the entry offsets. 2237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t offsets_offset = chunk.header_size(); 2247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entries_offset = dtohl(header->entriesStart); 2257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t offsets_length = sizeof(uint32_t) * entry_count; 2267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offsets_offset + offsets_length > entries_offset) { 2287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offsets overlap actual entry data."; 2297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entries_offset > chunk.size()) { 2337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offsets extend beyond chunk."; 2347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entries_offset & 0x03) { 2387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entries start at unaligned address."; 2397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check each entry offset. 2437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uint32_t* offsets = 2447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint32_t*>(reinterpret_cast<const uint8_t*>(header) + offsets_offset); 2457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski for (size_t i = 0; i < entry_count; i++) { 2467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint32_t offset = dtohl(offsets[i]); 2477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset != ResTable_type::NO_ENTRY) { 2487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check that the offset is aligned. 2497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset & 0x03) { 2507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offset at index " << i << " is not 4-byte aligned."; 2517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check that the offset doesn't overflow. 2557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset > std::numeric_limits<uint32_t>::max() - entries_offset) { 2567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Overflow in offset. 2577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offset at index " << i << " is too large."; 2587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski offset += entries_offset; 2627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset > chunk.size() - sizeof(ResTable_entry)) { 2637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Entry offset at index " << i << " is too large. No room for ResTable_entry."; 2647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>( 2687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(header) + offset); 2697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entry_size = dtohs(entry->size); 2707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_size < sizeof(*entry)) { 2717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "ResTable_entry size " << entry_size << " is too small."; 2727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Check the declared entrySize. 2767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_size > chunk.size() || offset > chunk.size() - entry_size) { 2777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "ResTable_entry size " << entry_size << " is too large."; 2787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // If this is a map entry, then keep validating. 2827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_size >= sizeof(ResTable_map_entry)) { 2837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(entry); 2847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t map_entry_count = dtohl(map->count); 2857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t map_entries_start = offset + entry_size; 2877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (map_entries_start & 0x03) { 2887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Map entries start at unaligned offset."; 2897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Each entry is sizeof(ResTable_map) big. 2937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (map_entry_count > ((chunk.size() - map_entries_start) / sizeof(ResTable_map))) { 2947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many map entries in ResTable_map_entry."; 2957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 2967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 2977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 2987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Great, all the map entries fit!. 2997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else { 3007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There needs to be room for one Res_value struct. 3017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (offset + entry_size > chunk.size() - sizeof(Res_value)) { 3027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "No room for Res_value after ResTable_entry."; 3037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 3047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Res_value* value = reinterpret_cast<const Res_value*>( 3077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<const uint8_t*>(entry) + entry_size); 3087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t value_size = dtohs(value->size); 3097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (value_size < sizeof(Res_value)) { 3107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Res_value is too small."; 3117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 3127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (value_size > chunk.size() || offset + entry_size > chunk.size() - value_size) { 3157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Res_value size is too large."; 3167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 3177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return true; 3227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 3237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 324da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskistd::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { 3257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 326da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski std::unique_ptr<LoadedPackage> loaded_package{new LoadedPackage()}; 327da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 3287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_package* header = chunk.header<ResTable_package>(); 3297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (header == nullptr) { 3307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_PACKAGE_TYPE is too small."; 331da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 3327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski loaded_package->package_id_ = dtohl(header->id); 335da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (loaded_package->package_id_ == 0) { 336da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski // Package ID of 0 means this is a shared library. 337da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_ = true; 338da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 339da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 340c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski if (header->header.headerSize >= sizeof(ResTable_package)) { 341c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski uint32_t type_id_offset = dtohl(header->typeIdOffset); 342c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski if (type_id_offset > std::numeric_limits<uint8_t>::max()) { 343c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski LOG(ERROR) << "Type ID offset in RES_TABLE_PACKAGE_TYPE is too large."; 344c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski return {}; 345c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski } 346c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski loaded_package->type_id_offset_ = static_cast<int>(type_id_offset); 347c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski } 348c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski 349da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), 350da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski &loaded_package->package_name_); 3517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // A TypeSpec builder. We use this to accumulate the set of Types 3537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // available for a TypeSpec, and later build a single, contiguous block 3547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // of memory that holds all the Types together with the TypeSpec. 3557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski std::unique_ptr<TypeSpecPtrBuilder> types_builder; 3567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Keep track of the last seen type index. Since type IDs are 1-based, 3587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // this records their index, which is 0-based (type ID - 1). 3597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski uint8_t last_type_idx = 0; 3607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); 3627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski while (iter.HasNext()) { 3637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Chunk child_chunk = iter.Next(); 3647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski switch (child_chunk.type()) { 3657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_STRING_POOL_TYPE: { 3667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uintptr_t pool_address = 3677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski reinterpret_cast<uintptr_t>(child_chunk.header<ResChunk_header>()); 3687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const uintptr_t header_address = reinterpret_cast<uintptr_t>(header); 3697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (pool_address == header_address + dtohl(header->typeStrings)) { 3707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // This string pool is the type string pool. 3717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski status_t err = loaded_package->type_string_pool_.setTo( 3727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski child_chunk.header<ResStringPool_header>(), child_chunk.size()); 3737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (err != NO_ERROR) { 3747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Corrupt package type string pool."; 375da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 3767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else if (pool_address == header_address + dtohl(header->keyStrings)) { 3787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // This string pool is the key string pool. 3797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski status_t err = loaded_package->key_string_pool_.setTo( 3807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski child_chunk.header<ResStringPool_header>(), child_chunk.size()); 3817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (err != NO_ERROR) { 3827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Corrupt package key string pool."; 383da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 3847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else { 3867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << "Too many string pool chunks found in package."; 3877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 3887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 3897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_TYPE_SPEC_TYPE: { 3917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_NAME("LoadTableTypeSpec"); 3927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 3937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Starting a new TypeSpec, so finish the old one if there was one. 3947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (types_builder) { 3957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtr type_spec_ptr = types_builder->Build(); 3967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec_ptr == nullptr) { 3977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many type configurations, overflow detected."; 398da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 3997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); 4017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_builder = {}; 4037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski last_type_idx = 0; 4047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>(); 4077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec == nullptr) { 4087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE is too small."; 409da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec->id == 0) { 4137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has invalid ID 0."; 414da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 417c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski if (loaded_package->type_id_offset_ + static_cast<int>(type_spec->id) > 418c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski std::numeric_limits<uint8_t>::max()) { 419c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has out of range ID."; 420c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski return {}; 421c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski } 422c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski 4237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // The data portion of this chunk contains entry_count 32bit entries, 4247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // each one representing a set of flags. 4257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Here we only validate that the chunk is well formed. 4267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t entry_count = dtohl(type_spec->entryCount); 4277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // There can only be 2^16 entries in a type, because that is the ID 4297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // space for entries (EEEE) in the resource ID 0xPPTTEEEE. 4307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_count > std::numeric_limits<uint16_t>::max()) { 4317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many entries in RES_TABLE_TYPE_SPEC_TYPE: " << entry_count << "."; 432da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (entry_count * sizeof(uint32_t) > chunk.data_size()) { 4367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk too small to hold entries in RES_TABLE_TYPE_SPEC_TYPE."; 437da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski last_type_idx = type_spec->id - 1; 4417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec); 4427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 4437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_TYPE_TYPE: { 4457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_type* type = child_chunk.header<ResTable_type>(); 4467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type == nullptr) { 4477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE is too small."; 448da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type->id == 0) { 4527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE has invalid ID 0."; 453da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Type chunks must be preceded by their TypeSpec chunks. 4577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (!types_builder || type->id - 1 != last_type_idx) { 4587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Found RES_TABLE_TYPE_TYPE chunk without " 4597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski "RES_TABLE_TYPE_SPEC_TYPE."; 460da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (!VerifyType(child_chunk)) { 464da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 4657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 4667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 4677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski types_builder->AddType(type); 4687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 4697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 470da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski case RES_TABLE_LIBRARY_TYPE: { 471da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const ResTable_lib_header* lib = child_chunk.header<ResTable_lib_header>(); 472da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (lib == nullptr) { 473da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_LIBRARY_TYPE is too small."; 474da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 475da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 476da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 477da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (child_chunk.data_size() / sizeof(ResTable_lib_entry) < dtohl(lib->count)) { 478da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LOG(ERROR) << "Chunk too small to hold entries in RES_TABLE_LIBRARY_TYPE."; 479da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 480da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 481da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 482da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_package_map_.reserve(dtohl(lib->count)); 483da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 484da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const ResTable_lib_entry* const entry_begin = 485da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski reinterpret_cast<const ResTable_lib_entry*>(child_chunk.data_ptr()); 486da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski const ResTable_lib_entry* const entry_end = entry_begin + dtohl(lib->count); 487da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski for (auto entry_iter = entry_begin; entry_iter != entry_end; ++entry_iter) { 488da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski std::string package_name; 489da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski util::ReadUtf16StringFromDevice(entry_iter->packageName, 490da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski arraysize(entry_iter->packageName), &package_name); 491da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 492da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) { 493da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski LOG(ERROR) << base::StringPrintf( 494da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.", 495da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski dtohl(entry_iter->packageId), package_name.c_str()); 496da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 497da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 498da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 499da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_package_map_.emplace_back(std::move(package_name), 500da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski dtohl(entry_iter->packageId)); 501da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 502da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 503da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } break; 504da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 5057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski default: 5067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); 5077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 5087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Finish the last TypeSpec. 5127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (types_builder) { 5137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski TypeSpecPtr type_spec_ptr = types_builder->Build(); 5147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (type_spec_ptr == nullptr) { 5157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Too many type configurations, overflow detected."; 516da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); 5197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (iter.HadError()) { 5227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << iter.GetLastError(); 523da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return {}; 5247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 525da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski return loaded_package; 5267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 5277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 528da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskibool LoadedArsc::LoadTable(const Chunk& chunk, bool load_as_shared_library) { 5297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 5307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const ResTable_header* header = chunk.header<ResTable_header>(); 5317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (header == nullptr) { 5327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Chunk RES_TABLE_TYPE is too small."; 5337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 5347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const size_t package_count = dtohl(header->packageCount); 5377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski size_t packages_seen = 0; 5387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski packages_.reserve(package_count); 5407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); 5427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski while (iter.HasNext()) { 5437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Chunk child_chunk = iter.Next(); 5447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski switch (child_chunk.type()) { 5457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_STRING_POOL_TYPE: 5467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Only use the first string pool. Ignore others. 5477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (global_string_pool_.getError() == NO_INIT) { 5487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski status_t err = global_string_pool_.setTo(child_chunk.header<ResStringPool_header>(), 5497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski child_chunk.size()); 5507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (err != NO_ERROR) { 5517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "Corrupt string pool."; 5527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 5537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } else { 5557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << "Multiple string pool chunks found in resource table."; 5567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 5587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_PACKAGE_TYPE: { 5607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (packages_seen + 1 > package_count) { 5617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << "More package chunks were found than the " << package_count 5627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski << " declared in the " 5637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski "header."; 5647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 5657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski packages_seen++; 5677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 568da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski std::unique_ptr<LoadedPackage> loaded_package = LoadedPackage::Load(child_chunk); 569da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (!loaded_package) { 5707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 5717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 572da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski 573da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski // Mark the package as dynamic if we are forcefully loading the Apk as a shared library. 574da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (loaded_package->package_id_ == kAppPackageId) { 575da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski loaded_package->dynamic_ = load_as_shared_library; 576da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski } 5777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski packages_.push_back(std::move(loaded_package)); 5787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } break; 5797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski default: 5817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); 5827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 5837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (iter.HadError()) { 5877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << iter.GetLastError(); 5887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return false; 5897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 5907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return true; 5917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 5927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 593da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskistd::unique_ptr<LoadedArsc> LoadedArsc::Load(const void* data, size_t len, 594da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski bool load_as_shared_library) { 5957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ATRACE_CALL(); 5967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 5977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski // Not using make_unique because the constructor is private. 5987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc()); 5997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski ChunkIterator iter(data, len); 6017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski while (iter.HasNext()) { 6027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski const Chunk chunk = iter.Next(); 6037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski switch (chunk.type()) { 6047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski case RES_TABLE_TYPE: 605da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski if (!loaded_arsc->LoadTable(chunk, load_as_shared_library)) { 6067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return {}; 6077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 6097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski default: 6117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); 6127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski break; 6137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski if (iter.HadError()) { 6177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski LOG(ERROR) << iter.GetLastError(); 6187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return {}; 6197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski } 6207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski return loaded_arsc; 6217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} 6227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski 6237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski} // namespace android 624