Loading libs/androidfw/AssetManager2.cpp +12 −26 Original line number Original line Diff line number Diff line Loading @@ -43,28 +43,19 @@ namespace { using EntryValue = std::variant<Res_value, incfs::verified_map_ptr<ResTable_map_entry>>; using EntryValue = std::variant<Res_value, incfs::verified_map_ptr<ResTable_map_entry>>; /* NOTE: table_entry has been verified in LoadedPackage::GetEntryFromOffset(), * and so access to ->value() and ->map_entry() are safe here */ base::expected<EntryValue, IOError> GetEntryValue( base::expected<EntryValue, IOError> GetEntryValue( incfs::verified_map_ptr<ResTable_entry> table_entry) { incfs::verified_map_ptr<ResTable_entry> table_entry) { const uint16_t entry_size = dtohs(table_entry->size); const uint16_t entry_size = table_entry->size(); // Check if the entry represents a bag value. // Check if the entry represents a bag value. if (entry_size >= sizeof(ResTable_map_entry) && if (entry_size >= sizeof(ResTable_map_entry) && table_entry->is_complex()) { (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX)) { return table_entry.convert<ResTable_map_entry>().verified(); const auto map_entry = table_entry.convert<ResTable_map_entry>(); if (!map_entry) { return base::unexpected(IOError::PAGES_MISSING); } return map_entry.verified(); } } // The entry represents a non-bag value. return table_entry->value(); const auto entry_value = table_entry.offset(entry_size).convert<Res_value>(); if (!entry_value) { return base::unexpected(IOError::PAGES_MISSING); } Res_value value; value.copyFrom_dtoh(entry_value.value()); return value; } } } // namespace } // namespace Loading Loading @@ -814,17 +805,12 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( return base::unexpected(std::nullopt); return base::unexpected(std::nullopt); } } auto best_entry_result = LoadedPackage::GetEntryFromOffset(best_type, best_offset); auto best_entry_verified = LoadedPackage::GetEntryFromOffset(best_type, best_offset); if (!best_entry_result.has_value()) { if (!best_entry_verified.has_value()) { return base::unexpected(best_entry_result.error()); return base::unexpected(best_entry_verified.error()); } const incfs::map_ptr<ResTable_entry> best_entry = *best_entry_result; if (!best_entry) { return base::unexpected(IOError::PAGES_MISSING); } } const auto entry = GetEntryValue(best_entry.verified()); const auto entry = GetEntryValue(*best_entry_verified); if (!entry.has_value()) { if (!entry.has_value()) { return base::unexpected(entry.error()); return base::unexpected(entry.error()); } } Loading @@ -837,7 +823,7 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( .package_name = &best_package->GetPackageName(), .package_name = &best_package->GetPackageName(), .type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1), .type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1), .entry_string_ref = StringPoolRef(best_package->GetKeyStringPool(), .entry_string_ref = StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index), (*best_entry_verified)->key()), .dynamic_ref_table = package_group.dynamic_ref_table.get(), .dynamic_ref_table = package_group.dynamic_ref_table.get(), }; }; } } Loading libs/androidfw/LoadedArsc.cpp +15 −9 Original line number Original line Diff line number Diff line Loading @@ -107,8 +107,8 @@ static bool VerifyResTableType(incfs::map_ptr<ResTable_type> header) { return true; return true; } } static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( static base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type, uint32_t entry_offset) { VerifyResTableEntry(incfs::verified_map_ptr<ResTable_type> type, uint32_t entry_offset) { // Check that the offset is aligned. // Check that the offset is aligned. if (UNLIKELY(entry_offset & 0x03U)) { if (UNLIKELY(entry_offset & 0x03U)) { LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned."; LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned."; Loading Loading @@ -136,7 +136,7 @@ static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( return base::unexpected(IOError::PAGES_MISSING); return base::unexpected(IOError::PAGES_MISSING); } } const size_t entry_size = dtohs(entry->size); const size_t entry_size = entry->size(); if (UNLIKELY(entry_size < sizeof(entry.value()))) { if (UNLIKELY(entry_size < sizeof(entry.value()))) { LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset << " is too small."; << " is too small."; Loading @@ -149,6 +149,11 @@ static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( return base::unexpected(std::nullopt); return base::unexpected(std::nullopt); } } // If entry is compact, value is already encoded, and a compact entry // cannot be a map_entry, we are done verifying if (entry->is_compact()) return entry.verified(); if (entry_size < sizeof(ResTable_map_entry)) { if (entry_size < sizeof(ResTable_map_entry)) { // There needs to be room for one Res_value struct. // There needs to be room for one Res_value struct. if (UNLIKELY(entry_offset + entry_size > chunk_size - sizeof(Res_value))) { if (UNLIKELY(entry_offset + entry_size > chunk_size - sizeof(Res_value))) { Loading Loading @@ -192,7 +197,7 @@ static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( return base::unexpected(std::nullopt); return base::unexpected(std::nullopt); } } } } return {}; return entry.verified(); } } LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei) LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei) Loading Loading @@ -228,7 +233,7 @@ uint32_t LoadedPackage::iterator::operator*() const { entryIndex_); entryIndex_); } } base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntry( base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntry( incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index) { incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index) { base::expected<uint32_t, NullOrIOError> entry_offset = GetEntryOffset(type_chunk, entry_index); base::expected<uint32_t, NullOrIOError> entry_offset = GetEntryOffset(type_chunk, entry_index); if (UNLIKELY(!entry_offset.has_value())) { if (UNLIKELY(!entry_offset.has_value())) { Loading Loading @@ -297,13 +302,14 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::GetEntryOffset( return value; return value; } } base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntryFromOffset( base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset) { LoadedPackage::GetEntryFromOffset(incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset) { auto valid = VerifyResTableEntry(type_chunk, offset); auto valid = VerifyResTableEntry(type_chunk, offset); if (UNLIKELY(!valid.has_value())) { if (UNLIKELY(!valid.has_value())) { return base::unexpected(valid.error()); return base::unexpected(valid.error()); } } return type_chunk.offset(offset + dtohl(type_chunk->entriesStart)).convert<ResTable_entry>(); return valid; } } base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations( base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations( Loading Loading @@ -400,7 +406,7 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName( return base::unexpected(IOError::PAGES_MISSING); return base::unexpected(IOError::PAGES_MISSING); } } if (dtohl(entry->key.index) == static_cast<uint32_t>(*key_idx)) { if (entry->key() == static_cast<uint32_t>(*key_idx)) { // The package ID will be overridden by the caller (due to runtime assignment of package // The package ID will be overridden by the caller (due to runtime assignment of package // IDs for shared libraries). // IDs for shared libraries). return make_resid(0x00, *type_idx + type_id_offset_ + 1, res_idx); return make_resid(0x00, *type_idx + type_id_offset_ + 1, res_idx); Loading libs/androidfw/ResourceTypes.cpp +18 −28 Original line number Original line Diff line number Diff line Loading @@ -4487,20 +4487,14 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag return err; return err; } } if ((dtohs(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) != 0) { if (entry.entry->map_entry()) { if (!mayBeBag) { if (!mayBeBag) { ALOGW("Requesting resource 0x%08x failed because it is complex\n", resID); ALOGW("Requesting resource 0x%08x failed because it is complex\n", resID); } } return BAD_VALUE; return BAD_VALUE; } } const Res_value* value = reinterpret_cast<const Res_value*>( *outValue = entry.entry->value(); reinterpret_cast<const uint8_t*>(entry.entry) + entry.entry->size); outValue->size = dtohs(value->size); outValue->res0 = value->res0; outValue->dataType = value->dataType; outValue->data = dtohl(value->data); // The reference may be pointing to a resource in a shared library. These // The reference may be pointing to a resource in a shared library. These // references have build-time generated package IDs. These ids may not match // references have build-time generated package IDs. These ids may not match Loading Loading @@ -4691,11 +4685,10 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag, return err; return err; } } const uint16_t entrySize = dtohs(entry.entry->size); const uint16_t entrySize = entry.entry->size(); const uint32_t parent = entrySize >= sizeof(ResTable_map_entry) const ResTable_map_entry* map_entry = entry.entry->map_entry(); ? dtohl(((const ResTable_map_entry*)entry.entry)->parent.ident) : 0; const uint32_t parent = map_entry ? dtohl(map_entry->parent.ident) : 0; const uint32_t count = entrySize >= sizeof(ResTable_map_entry) const uint32_t count = map_entry ? dtohl(map_entry->count) : 0; ? dtohl(((const ResTable_map_entry*)entry.entry)->count) : 0; size_t N = count; size_t N = count; Loading Loading @@ -4759,7 +4752,7 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag, // Now merge in the new attributes... // Now merge in the new attributes... size_t curOff = (reinterpret_cast<uintptr_t>(entry.entry) - reinterpret_cast<uintptr_t>(entry.type)) size_t curOff = (reinterpret_cast<uintptr_t>(entry.entry) - reinterpret_cast<uintptr_t>(entry.type)) + dtohs(entry.entry->size); + entrySize; const ResTable_map* map; const ResTable_map* map; bag_entry* entries = (bag_entry*)(set+1); bag_entry* entries = (bag_entry*)(set+1); size_t curEntry = 0; size_t curEntry = 0; Loading Loading @@ -5137,7 +5130,7 @@ uint32_t ResTable::findEntry(const PackageGroup* group, ssize_t typeIndex, const continue; continue; } } if (dtohl(entry->key.index) == (size_t) *ei) { if (entry->key() == (size_t) *ei) { uint32_t resId = Res_MAKEID(group->id - 1, typeIndex, iter.index()); uint32_t resId = Res_MAKEID(group->id - 1, typeIndex, iter.index()); if (outTypeSpecFlags) { if (outTypeSpecFlags) { Entry result; Entry result; Loading Loading @@ -6651,8 +6644,8 @@ status_t ResTable::getEntry( const ResTable_entry* const entry = reinterpret_cast<const ResTable_entry*>( const ResTable_entry* const entry = reinterpret_cast<const ResTable_entry*>( reinterpret_cast<const uint8_t*>(bestType) + bestOffset); reinterpret_cast<const uint8_t*>(bestType) + bestOffset); if (dtohs(entry->size) < sizeof(*entry)) { if (entry->size() < sizeof(*entry)) { ALOGW("ResTable_entry size 0x%x is too small", dtohs(entry->size)); ALOGW("ResTable_entry size 0x%zx is too small", entry->size()); return BAD_TYPE; return BAD_TYPE; } } Loading @@ -6663,7 +6656,7 @@ status_t ResTable::getEntry( outEntry->specFlags = specFlags; outEntry->specFlags = specFlags; outEntry->package = bestPackage; outEntry->package = bestPackage; outEntry->typeStr = StringPoolRef(&bestPackage->typeStrings, actualTypeIndex - bestPackage->typeIdOffset); outEntry->typeStr = StringPoolRef(&bestPackage->typeStrings, actualTypeIndex - bestPackage->typeIdOffset); outEntry->keyStr = StringPoolRef(&bestPackage->keyStrings, dtohl(entry->key.index)); outEntry->keyStr = StringPoolRef(&bestPackage->keyStrings, entry->key()); } } return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -7734,7 +7727,7 @@ void ResTable::print(bool inclValues) const continue; continue; } } uintptr_t esize = dtohs(ent->size); uintptr_t esize = ent->size(); if ((esize&0x3) != 0) { if ((esize&0x3) != 0) { printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize); printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize); continue; continue; Loading @@ -7746,30 +7739,27 @@ void ResTable::print(bool inclValues) const } } const Res_value* valuePtr = NULL; const Res_value* valuePtr = NULL; const ResTable_map_entry* bagPtr = NULL; const ResTable_map_entry* bagPtr = ent->map_entry(); Res_value value; Res_value value; if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) { if (bagPtr) { printf("<bag>"); printf("<bag>"); bagPtr = (const ResTable_map_entry*)ent; } else { } else { valuePtr = (const Res_value*) value = ent->value(); (((const uint8_t*)ent) + esize); value.copyFrom_dtoh(*valuePtr); printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", (int)value.dataType, (int)value.data, (int)value.dataType, (int)value.data, (int)value.size, (int)value.res0); (int)value.size, (int)value.res0); } } if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) { if (ent->flags() & ResTable_entry::FLAG_PUBLIC) { printf(" (PUBLIC)"); printf(" (PUBLIC)"); } } printf("\n"); printf("\n"); if (inclValues) { if (inclValues) { if (valuePtr != NULL) { if (bagPtr == NULL) { printf(" "); printf(" "); print_value(typeConfigs->package, value); print_value(typeConfigs->package, value); } else if (bagPtr != NULL) { } else { const int N = dtohl(bagPtr->count); const int N = dtohl(bagPtr->count); const uint8_t* baseMapPtr = (const uint8_t*)ent; const uint8_t* baseMapPtr = (const uint8_t*)ent; size_t mapOffset = esize; size_t mapOffset = esize; Loading libs/androidfw/TypeWrappers.cpp +3 −3 Original line number Original line Diff line number Diff line Loading @@ -91,11 +91,11 @@ const ResTable_entry* TypeVariant::iterator::operator*() const { if (reinterpret_cast<uintptr_t>(entry) > containerEnd - sizeof(*entry)) { if (reinterpret_cast<uintptr_t>(entry) > containerEnd - sizeof(*entry)) { ALOGE("Entry offset at index %u points outside the Type's boundaries", mIndex); ALOGE("Entry offset at index %u points outside the Type's boundaries", mIndex); return NULL; return NULL; } else if (reinterpret_cast<uintptr_t>(entry) + dtohs(entry->size) > containerEnd) { } else if (reinterpret_cast<uintptr_t>(entry) + entry->size() > containerEnd) { ALOGE("Entry at index %u extends beyond Type's boundaries", mIndex); ALOGE("Entry at index %u extends beyond Type's boundaries", mIndex); return NULL; return NULL; } else if (dtohs(entry->size) < sizeof(*entry)) { } else if (entry->size() < sizeof(*entry)) { ALOGE("Entry at index %u is too small (%u)", mIndex, dtohs(entry->size)); ALOGE("Entry at index %u is too small (%zu)", mIndex, entry->size()); return NULL; return NULL; } } return entry; return entry; Loading libs/androidfw/include/androidfw/LoadedArsc.h +4 −4 Original line number Original line Diff line number Diff line Loading @@ -166,14 +166,14 @@ class LoadedPackage { base::expected<uint32_t, NullOrIOError> FindEntryByName(const std::u16string& type_name, base::expected<uint32_t, NullOrIOError> FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const; const std::u16string& entry_name) const; static base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> GetEntry( static base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); GetEntry(incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); static base::expected<uint32_t, NullOrIOError> GetEntryOffset( static base::expected<uint32_t, NullOrIOError> GetEntryOffset( incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); static base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> GetEntryFromOffset( static base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset); GetEntryFromOffset(incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset); // Returns the string pool where type names are stored. // Returns the string pool where type names are stored. const ResStringPool* GetTypeStringPool() const { const ResStringPool* GetTypeStringPool() const { Loading Loading
libs/androidfw/AssetManager2.cpp +12 −26 Original line number Original line Diff line number Diff line Loading @@ -43,28 +43,19 @@ namespace { using EntryValue = std::variant<Res_value, incfs::verified_map_ptr<ResTable_map_entry>>; using EntryValue = std::variant<Res_value, incfs::verified_map_ptr<ResTable_map_entry>>; /* NOTE: table_entry has been verified in LoadedPackage::GetEntryFromOffset(), * and so access to ->value() and ->map_entry() are safe here */ base::expected<EntryValue, IOError> GetEntryValue( base::expected<EntryValue, IOError> GetEntryValue( incfs::verified_map_ptr<ResTable_entry> table_entry) { incfs::verified_map_ptr<ResTable_entry> table_entry) { const uint16_t entry_size = dtohs(table_entry->size); const uint16_t entry_size = table_entry->size(); // Check if the entry represents a bag value. // Check if the entry represents a bag value. if (entry_size >= sizeof(ResTable_map_entry) && if (entry_size >= sizeof(ResTable_map_entry) && table_entry->is_complex()) { (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX)) { return table_entry.convert<ResTable_map_entry>().verified(); const auto map_entry = table_entry.convert<ResTable_map_entry>(); if (!map_entry) { return base::unexpected(IOError::PAGES_MISSING); } return map_entry.verified(); } } // The entry represents a non-bag value. return table_entry->value(); const auto entry_value = table_entry.offset(entry_size).convert<Res_value>(); if (!entry_value) { return base::unexpected(IOError::PAGES_MISSING); } Res_value value; value.copyFrom_dtoh(entry_value.value()); return value; } } } // namespace } // namespace Loading Loading @@ -814,17 +805,12 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( return base::unexpected(std::nullopt); return base::unexpected(std::nullopt); } } auto best_entry_result = LoadedPackage::GetEntryFromOffset(best_type, best_offset); auto best_entry_verified = LoadedPackage::GetEntryFromOffset(best_type, best_offset); if (!best_entry_result.has_value()) { if (!best_entry_verified.has_value()) { return base::unexpected(best_entry_result.error()); return base::unexpected(best_entry_verified.error()); } const incfs::map_ptr<ResTable_entry> best_entry = *best_entry_result; if (!best_entry) { return base::unexpected(IOError::PAGES_MISSING); } } const auto entry = GetEntryValue(best_entry.verified()); const auto entry = GetEntryValue(*best_entry_verified); if (!entry.has_value()) { if (!entry.has_value()) { return base::unexpected(entry.error()); return base::unexpected(entry.error()); } } Loading @@ -837,7 +823,7 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( .package_name = &best_package->GetPackageName(), .package_name = &best_package->GetPackageName(), .type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1), .type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1), .entry_string_ref = StringPoolRef(best_package->GetKeyStringPool(), .entry_string_ref = StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index), (*best_entry_verified)->key()), .dynamic_ref_table = package_group.dynamic_ref_table.get(), .dynamic_ref_table = package_group.dynamic_ref_table.get(), }; }; } } Loading
libs/androidfw/LoadedArsc.cpp +15 −9 Original line number Original line Diff line number Diff line Loading @@ -107,8 +107,8 @@ static bool VerifyResTableType(incfs::map_ptr<ResTable_type> header) { return true; return true; } } static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( static base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type, uint32_t entry_offset) { VerifyResTableEntry(incfs::verified_map_ptr<ResTable_type> type, uint32_t entry_offset) { // Check that the offset is aligned. // Check that the offset is aligned. if (UNLIKELY(entry_offset & 0x03U)) { if (UNLIKELY(entry_offset & 0x03U)) { LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned."; LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned."; Loading Loading @@ -136,7 +136,7 @@ static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( return base::unexpected(IOError::PAGES_MISSING); return base::unexpected(IOError::PAGES_MISSING); } } const size_t entry_size = dtohs(entry->size); const size_t entry_size = entry->size(); if (UNLIKELY(entry_size < sizeof(entry.value()))) { if (UNLIKELY(entry_size < sizeof(entry.value()))) { LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset << " is too small."; << " is too small."; Loading @@ -149,6 +149,11 @@ static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( return base::unexpected(std::nullopt); return base::unexpected(std::nullopt); } } // If entry is compact, value is already encoded, and a compact entry // cannot be a map_entry, we are done verifying if (entry->is_compact()) return entry.verified(); if (entry_size < sizeof(ResTable_map_entry)) { if (entry_size < sizeof(ResTable_map_entry)) { // There needs to be room for one Res_value struct. // There needs to be room for one Res_value struct. if (UNLIKELY(entry_offset + entry_size > chunk_size - sizeof(Res_value))) { if (UNLIKELY(entry_offset + entry_size > chunk_size - sizeof(Res_value))) { Loading Loading @@ -192,7 +197,7 @@ static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry( return base::unexpected(std::nullopt); return base::unexpected(std::nullopt); } } } } return {}; return entry.verified(); } } LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei) LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei) Loading Loading @@ -228,7 +233,7 @@ uint32_t LoadedPackage::iterator::operator*() const { entryIndex_); entryIndex_); } } base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntry( base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntry( incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index) { incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index) { base::expected<uint32_t, NullOrIOError> entry_offset = GetEntryOffset(type_chunk, entry_index); base::expected<uint32_t, NullOrIOError> entry_offset = GetEntryOffset(type_chunk, entry_index); if (UNLIKELY(!entry_offset.has_value())) { if (UNLIKELY(!entry_offset.has_value())) { Loading Loading @@ -297,13 +302,14 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::GetEntryOffset( return value; return value; } } base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntryFromOffset( base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset) { LoadedPackage::GetEntryFromOffset(incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset) { auto valid = VerifyResTableEntry(type_chunk, offset); auto valid = VerifyResTableEntry(type_chunk, offset); if (UNLIKELY(!valid.has_value())) { if (UNLIKELY(!valid.has_value())) { return base::unexpected(valid.error()); return base::unexpected(valid.error()); } } return type_chunk.offset(offset + dtohl(type_chunk->entriesStart)).convert<ResTable_entry>(); return valid; } } base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations( base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations( Loading Loading @@ -400,7 +406,7 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName( return base::unexpected(IOError::PAGES_MISSING); return base::unexpected(IOError::PAGES_MISSING); } } if (dtohl(entry->key.index) == static_cast<uint32_t>(*key_idx)) { if (entry->key() == static_cast<uint32_t>(*key_idx)) { // The package ID will be overridden by the caller (due to runtime assignment of package // The package ID will be overridden by the caller (due to runtime assignment of package // IDs for shared libraries). // IDs for shared libraries). return make_resid(0x00, *type_idx + type_id_offset_ + 1, res_idx); return make_resid(0x00, *type_idx + type_id_offset_ + 1, res_idx); Loading
libs/androidfw/ResourceTypes.cpp +18 −28 Original line number Original line Diff line number Diff line Loading @@ -4487,20 +4487,14 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag return err; return err; } } if ((dtohs(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) != 0) { if (entry.entry->map_entry()) { if (!mayBeBag) { if (!mayBeBag) { ALOGW("Requesting resource 0x%08x failed because it is complex\n", resID); ALOGW("Requesting resource 0x%08x failed because it is complex\n", resID); } } return BAD_VALUE; return BAD_VALUE; } } const Res_value* value = reinterpret_cast<const Res_value*>( *outValue = entry.entry->value(); reinterpret_cast<const uint8_t*>(entry.entry) + entry.entry->size); outValue->size = dtohs(value->size); outValue->res0 = value->res0; outValue->dataType = value->dataType; outValue->data = dtohl(value->data); // The reference may be pointing to a resource in a shared library. These // The reference may be pointing to a resource in a shared library. These // references have build-time generated package IDs. These ids may not match // references have build-time generated package IDs. These ids may not match Loading Loading @@ -4691,11 +4685,10 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag, return err; return err; } } const uint16_t entrySize = dtohs(entry.entry->size); const uint16_t entrySize = entry.entry->size(); const uint32_t parent = entrySize >= sizeof(ResTable_map_entry) const ResTable_map_entry* map_entry = entry.entry->map_entry(); ? dtohl(((const ResTable_map_entry*)entry.entry)->parent.ident) : 0; const uint32_t parent = map_entry ? dtohl(map_entry->parent.ident) : 0; const uint32_t count = entrySize >= sizeof(ResTable_map_entry) const uint32_t count = map_entry ? dtohl(map_entry->count) : 0; ? dtohl(((const ResTable_map_entry*)entry.entry)->count) : 0; size_t N = count; size_t N = count; Loading Loading @@ -4759,7 +4752,7 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag, // Now merge in the new attributes... // Now merge in the new attributes... size_t curOff = (reinterpret_cast<uintptr_t>(entry.entry) - reinterpret_cast<uintptr_t>(entry.type)) size_t curOff = (reinterpret_cast<uintptr_t>(entry.entry) - reinterpret_cast<uintptr_t>(entry.type)) + dtohs(entry.entry->size); + entrySize; const ResTable_map* map; const ResTable_map* map; bag_entry* entries = (bag_entry*)(set+1); bag_entry* entries = (bag_entry*)(set+1); size_t curEntry = 0; size_t curEntry = 0; Loading Loading @@ -5137,7 +5130,7 @@ uint32_t ResTable::findEntry(const PackageGroup* group, ssize_t typeIndex, const continue; continue; } } if (dtohl(entry->key.index) == (size_t) *ei) { if (entry->key() == (size_t) *ei) { uint32_t resId = Res_MAKEID(group->id - 1, typeIndex, iter.index()); uint32_t resId = Res_MAKEID(group->id - 1, typeIndex, iter.index()); if (outTypeSpecFlags) { if (outTypeSpecFlags) { Entry result; Entry result; Loading Loading @@ -6651,8 +6644,8 @@ status_t ResTable::getEntry( const ResTable_entry* const entry = reinterpret_cast<const ResTable_entry*>( const ResTable_entry* const entry = reinterpret_cast<const ResTable_entry*>( reinterpret_cast<const uint8_t*>(bestType) + bestOffset); reinterpret_cast<const uint8_t*>(bestType) + bestOffset); if (dtohs(entry->size) < sizeof(*entry)) { if (entry->size() < sizeof(*entry)) { ALOGW("ResTable_entry size 0x%x is too small", dtohs(entry->size)); ALOGW("ResTable_entry size 0x%zx is too small", entry->size()); return BAD_TYPE; return BAD_TYPE; } } Loading @@ -6663,7 +6656,7 @@ status_t ResTable::getEntry( outEntry->specFlags = specFlags; outEntry->specFlags = specFlags; outEntry->package = bestPackage; outEntry->package = bestPackage; outEntry->typeStr = StringPoolRef(&bestPackage->typeStrings, actualTypeIndex - bestPackage->typeIdOffset); outEntry->typeStr = StringPoolRef(&bestPackage->typeStrings, actualTypeIndex - bestPackage->typeIdOffset); outEntry->keyStr = StringPoolRef(&bestPackage->keyStrings, dtohl(entry->key.index)); outEntry->keyStr = StringPoolRef(&bestPackage->keyStrings, entry->key()); } } return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -7734,7 +7727,7 @@ void ResTable::print(bool inclValues) const continue; continue; } } uintptr_t esize = dtohs(ent->size); uintptr_t esize = ent->size(); if ((esize&0x3) != 0) { if ((esize&0x3) != 0) { printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize); printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize); continue; continue; Loading @@ -7746,30 +7739,27 @@ void ResTable::print(bool inclValues) const } } const Res_value* valuePtr = NULL; const Res_value* valuePtr = NULL; const ResTable_map_entry* bagPtr = NULL; const ResTable_map_entry* bagPtr = ent->map_entry(); Res_value value; Res_value value; if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) { if (bagPtr) { printf("<bag>"); printf("<bag>"); bagPtr = (const ResTable_map_entry*)ent; } else { } else { valuePtr = (const Res_value*) value = ent->value(); (((const uint8_t*)ent) + esize); value.copyFrom_dtoh(*valuePtr); printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", (int)value.dataType, (int)value.data, (int)value.dataType, (int)value.data, (int)value.size, (int)value.res0); (int)value.size, (int)value.res0); } } if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) { if (ent->flags() & ResTable_entry::FLAG_PUBLIC) { printf(" (PUBLIC)"); printf(" (PUBLIC)"); } } printf("\n"); printf("\n"); if (inclValues) { if (inclValues) { if (valuePtr != NULL) { if (bagPtr == NULL) { printf(" "); printf(" "); print_value(typeConfigs->package, value); print_value(typeConfigs->package, value); } else if (bagPtr != NULL) { } else { const int N = dtohl(bagPtr->count); const int N = dtohl(bagPtr->count); const uint8_t* baseMapPtr = (const uint8_t*)ent; const uint8_t* baseMapPtr = (const uint8_t*)ent; size_t mapOffset = esize; size_t mapOffset = esize; Loading
libs/androidfw/TypeWrappers.cpp +3 −3 Original line number Original line Diff line number Diff line Loading @@ -91,11 +91,11 @@ const ResTable_entry* TypeVariant::iterator::operator*() const { if (reinterpret_cast<uintptr_t>(entry) > containerEnd - sizeof(*entry)) { if (reinterpret_cast<uintptr_t>(entry) > containerEnd - sizeof(*entry)) { ALOGE("Entry offset at index %u points outside the Type's boundaries", mIndex); ALOGE("Entry offset at index %u points outside the Type's boundaries", mIndex); return NULL; return NULL; } else if (reinterpret_cast<uintptr_t>(entry) + dtohs(entry->size) > containerEnd) { } else if (reinterpret_cast<uintptr_t>(entry) + entry->size() > containerEnd) { ALOGE("Entry at index %u extends beyond Type's boundaries", mIndex); ALOGE("Entry at index %u extends beyond Type's boundaries", mIndex); return NULL; return NULL; } else if (dtohs(entry->size) < sizeof(*entry)) { } else if (entry->size() < sizeof(*entry)) { ALOGE("Entry at index %u is too small (%u)", mIndex, dtohs(entry->size)); ALOGE("Entry at index %u is too small (%zu)", mIndex, entry->size()); return NULL; return NULL; } } return entry; return entry; Loading
libs/androidfw/include/androidfw/LoadedArsc.h +4 −4 Original line number Original line Diff line number Diff line Loading @@ -166,14 +166,14 @@ class LoadedPackage { base::expected<uint32_t, NullOrIOError> FindEntryByName(const std::u16string& type_name, base::expected<uint32_t, NullOrIOError> FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const; const std::u16string& entry_name) const; static base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> GetEntry( static base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); GetEntry(incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); static base::expected<uint32_t, NullOrIOError> GetEntryOffset( static base::expected<uint32_t, NullOrIOError> GetEntryOffset( incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index); static base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> GetEntryFromOffset( static base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError> incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset); GetEntryFromOffset(incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset); // Returns the string pool where type names are stored. // Returns the string pool where type names are stored. const ResStringPool* GetTypeStringPool() const { const ResStringPool* GetTypeStringPool() const { Loading