Loading libs/androidfw/LoadedArsc.cpp +19 −2 Original line number Diff line number Diff line Loading @@ -116,7 +116,10 @@ bool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTab LoadedArscEntry* out_entry, ResTable_config* out_selected_config, uint32_t* out_flags) const { ATRACE_CALL(); const TypeSpecPtr& ptr = type_specs_[type_idx]; // If the type IDs are offset in this package, we need to take that into account when searching // for a type. const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_]; if (ptr == nullptr) { return false; } Loading Loading @@ -334,6 +337,15 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { loaded_package->dynamic_ = true; } if (header->header.headerSize >= sizeof(ResTable_package)) { uint32_t type_id_offset = dtohl(header->typeIdOffset); if (type_id_offset > std::numeric_limits<uint8_t>::max()) { LOG(ERROR) << "Type ID offset in RES_TABLE_PACKAGE_TYPE is too large."; return {}; } loaded_package->type_id_offset_ = static_cast<int>(type_id_offset); } util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), &loaded_package->package_name_); Loading Loading @@ -385,7 +397,6 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { LOG(ERROR) << "Too many type configurations, overflow detected."; return {}; } loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); types_builder = {}; Loading @@ -403,6 +414,12 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { return {}; } if (loaded_package->type_id_offset_ + static_cast<int>(type_spec->id) > std::numeric_limits<uint8_t>::max()) { LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has out of range ID."; return {}; } // The data portion of this chunk contains entry_count 32bit entries, // each one representing a set of flags. // Here we only validate that the chunk is well formed. Loading libs/androidfw/include/androidfw/LoadedArsc.h +1 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ class LoadedPackage { std::string package_name_; int package_id_ = -1; bool dynamic_ = false; int type_id_offset_ = 0; ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_; std::vector<DynamicPackageEntry> dynamic_package_map_; Loading libs/androidfw/tests/LoadedArsc_test.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,36 @@ TEST(LoadedArscTest, LoadAppAsSharedLibrary) { EXPECT_EQ(0x7f, packages[0]->GetPackageId()); } TEST(LoadedArscTest, LoadFeatureSplit) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc", &contents)); std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size()); ASSERT_NE(nullptr, loaded_arsc); ResTable_config desired_config; memset(&desired_config, 0, sizeof(desired_config)); LoadedArscEntry entry; ResTable_config selected_config; uint32_t flags; ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test3, desired_config, &entry, &selected_config, &flags)); size_t len; const char16_t* type_name16 = entry.type_string_ref.string16(&len); ASSERT_NE(nullptr, type_name16); ASSERT_NE(0u, len); size_t utf8_len = utf16_to_utf8_length(type_name16, len); std::string type_name; type_name.resize(utf8_len); utf16_to_utf8(type_name16, len, &*type_name.begin(), utf8_len + 1); EXPECT_EQ(std::string("string"), type_name); } // structs with size fields (like Res_value, ResTable_entry) should be // backwards and forwards compatible (aka checking the size field against // sizeof(Res_value) might not be backwards compatible. Loading libs/androidfw/tests/data/feature/feature.apk (1.34 KiB) File changed.No diff preview for this file type. View original file View changed file Loading
libs/androidfw/LoadedArsc.cpp +19 −2 Original line number Diff line number Diff line Loading @@ -116,7 +116,10 @@ bool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTab LoadedArscEntry* out_entry, ResTable_config* out_selected_config, uint32_t* out_flags) const { ATRACE_CALL(); const TypeSpecPtr& ptr = type_specs_[type_idx]; // If the type IDs are offset in this package, we need to take that into account when searching // for a type. const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_]; if (ptr == nullptr) { return false; } Loading Loading @@ -334,6 +337,15 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { loaded_package->dynamic_ = true; } if (header->header.headerSize >= sizeof(ResTable_package)) { uint32_t type_id_offset = dtohl(header->typeIdOffset); if (type_id_offset > std::numeric_limits<uint8_t>::max()) { LOG(ERROR) << "Type ID offset in RES_TABLE_PACKAGE_TYPE is too large."; return {}; } loaded_package->type_id_offset_ = static_cast<int>(type_id_offset); } util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), &loaded_package->package_name_); Loading Loading @@ -385,7 +397,6 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { LOG(ERROR) << "Too many type configurations, overflow detected."; return {}; } loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); types_builder = {}; Loading @@ -403,6 +414,12 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) { return {}; } if (loaded_package->type_id_offset_ + static_cast<int>(type_spec->id) > std::numeric_limits<uint8_t>::max()) { LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has out of range ID."; return {}; } // The data portion of this chunk contains entry_count 32bit entries, // each one representing a set of flags. // Here we only validate that the chunk is well formed. Loading
libs/androidfw/include/androidfw/LoadedArsc.h +1 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ class LoadedPackage { std::string package_name_; int package_id_ = -1; bool dynamic_ = false; int type_id_offset_ = 0; ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_; std::vector<DynamicPackageEntry> dynamic_package_map_; Loading
libs/androidfw/tests/LoadedArsc_test.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,36 @@ TEST(LoadedArscTest, LoadAppAsSharedLibrary) { EXPECT_EQ(0x7f, packages[0]->GetPackageId()); } TEST(LoadedArscTest, LoadFeatureSplit) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc", &contents)); std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size()); ASSERT_NE(nullptr, loaded_arsc); ResTable_config desired_config; memset(&desired_config, 0, sizeof(desired_config)); LoadedArscEntry entry; ResTable_config selected_config; uint32_t flags; ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test3, desired_config, &entry, &selected_config, &flags)); size_t len; const char16_t* type_name16 = entry.type_string_ref.string16(&len); ASSERT_NE(nullptr, type_name16); ASSERT_NE(0u, len); size_t utf8_len = utf16_to_utf8_length(type_name16, len); std::string type_name; type_name.resize(utf8_len); utf16_to_utf8(type_name16, len, &*type_name.begin(), utf8_len + 1); EXPECT_EQ(std::string("string"), type_name); } // structs with size fields (like Res_value, ResTable_entry) should be // backwards and forwards compatible (aka checking the size field against // sizeof(Res_value) might not be backwards compatible. Loading
libs/androidfw/tests/data/feature/feature.apk (1.34 KiB) File changed.No diff preview for this file type. View original file View changed file