summaryrefslogtreecommitdiff
path: root/libs/androidfw/LoadedArsc.cpp
diff options
context:
space:
mode:
author Adam Lesinski <adamlesinski@google.com> 2018-02-09 11:01:36 -0800
committer Adam Lesinski <adamlesinski@google.com> 2018-02-09 12:43:07 -0800
commitdfeb7ceb2afc1f630e7d2afdd9f37ef70386e146 (patch)
tree6c5939b7974f1a55cd874fda4b76a2610a669290 /libs/androidfw/LoadedArsc.cpp
parentec7f06cc372a7298c85bf96cb4133d7dc8807419 (diff)
Revert "AssetManager2: Allow out of order type/type spec"
This reverts commit 78695c354342bd95ba5f63937b4e789139b50072. Bug: 73134570 Change-Id: I6acc35372d9071d067d2fb7caa775ee9ba689811
Diffstat (limited to 'libs/androidfw/LoadedArsc.cpp')
-rw-r--r--libs/androidfw/LoadedArsc.cpp84
1 files changed, 51 insertions, 33 deletions
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index a65d49b7e32f..1d2c597c4c8c 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -409,10 +409,14 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
util::ReadUtf16StringFromDevice(header->name, arraysize(header->name),
&loaded_package->package_name_);
- // A map of TypeSpec builders, each associated with an type index.
- // We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
- // contiguous block of memory that holds all the Types together with the TypeSpec.
- std::unordered_map<int, std::unique_ptr<TypeSpecPtrBuilder>> type_builder_map;
+ // A TypeSpec builder. We use this to accumulate the set of Types
+ // available for a TypeSpec, and later build a single, contiguous block
+ // of memory that holds all the Types together with the TypeSpec.
+ std::unique_ptr<TypeSpecPtrBuilder> types_builder;
+
+ // Keep track of the last seen type index. Since type IDs are 1-based,
+ // this records their index, which is 0-based (type ID - 1).
+ uint8_t last_type_idx = 0;
ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
while (iter.HasNext()) {
@@ -446,6 +450,28 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
case RES_TABLE_TYPE_SPEC_TYPE: {
ATRACE_NAME("LoadTableTypeSpec");
+ // Starting a new TypeSpec, so finish the old one if there was one.
+ if (types_builder) {
+ TypeSpecPtr type_spec_ptr = types_builder->Build();
+ if (type_spec_ptr == nullptr) {
+ LOG(ERROR) << "Too many type configurations, overflow detected.";
+ return {};
+ }
+
+ // We only add the type to the package if there is no IDMAP, or if the type is
+ // overlaying something.
+ if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
+ // If this is an overlay, insert it at the target type ID.
+ if (type_spec_ptr->idmap_entries != nullptr) {
+ last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
+ }
+ loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
+ }
+
+ types_builder = {};
+ last_type_idx = 0;
+ }
+
const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>();
if (type_spec == nullptr) {
LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small.";
@@ -480,6 +506,8 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
return {};
}
+ last_type_idx = type_spec->id - 1;
+
// If this is an overlay, associate the mapping of this type to the target type
// from the IDMAP.
const IdmapEntry_header* idmap_entry_header = nullptr;
@@ -487,13 +515,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id);
}
- std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
- if (builder_ptr == nullptr) {
- builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
- } else {
- LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
- type_spec->id);
- }
+ types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
} break;
case RES_TABLE_TYPE_TYPE: {
@@ -508,15 +530,12 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
}
// Type chunks must be preceded by their TypeSpec chunks.
- std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type->id - 1];
- if (builder_ptr != nullptr) {
- builder_ptr->AddType(type);
- } else {
- LOG(ERROR) << StringPrintf(
- "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.",
- type->id);
+ if (!types_builder || type->id - 1 != last_type_idx) {
+ LOG(ERROR) << "RES_TABLE_TYPE_TYPE found without preceding RES_TABLE_TYPE_SPEC_TYPE.";
return {};
}
+
+ types_builder->AddType(type);
} break;
case RES_TABLE_LIBRARY_TYPE: {
@@ -542,7 +561,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
arraysize(entry_iter->packageName), &package_name);
if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) {
- LOG(ERROR) << StringPrintf(
+ LOG(ERROR) << base::StringPrintf(
"Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.",
dtohl(entry_iter->packageId), package_name.c_str());
return {};
@@ -555,20 +574,14 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
} break;
default:
- LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+ LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
break;
}
}
- if (iter.HadError()) {
- LOG(ERROR) << iter.GetLastError();
- return {};
- }
-
- // Flatten and construct the TypeSpecs.
- for (auto& entry : type_builder_map) {
- uint8_t type_idx = static_cast<uint8_t>(entry.first);
- TypeSpecPtr type_spec_ptr = entry.second->Build();
+ // Finish the last TypeSpec.
+ if (types_builder) {
+ TypeSpecPtr type_spec_ptr = types_builder->Build();
if (type_spec_ptr == nullptr) {
LOG(ERROR) << "Too many type configurations, overflow detected.";
return {};
@@ -579,15 +592,20 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
// If this is an overlay, insert it at the target type ID.
if (type_spec_ptr->idmap_entries != nullptr) {
- type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
+ last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
}
- loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
+ loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
}
}
+ if (iter.HadError()) {
+ LOG(ERROR) << iter.GetLastError();
+ return {};
+ }
return std::move(loaded_package);
}
+
bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
bool load_as_shared_library) {
ATRACE_CALL();
@@ -637,7 +655,7 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
} break;
default:
- LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+ LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
break;
}
}
@@ -669,7 +687,7 @@ std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data,
break;
default:
- LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
+ LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
break;
}
}