Merge "AAPT2: Fix parsing ResTable_type"
This commit is contained in:
committed by
Android (Google) Code Review
commit
df2870df9a
@@ -212,7 +212,7 @@ const LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const {
|
||||
|
||||
static bool VerifyType(const Chunk& chunk) {
|
||||
ATRACE_CALL();
|
||||
const ResTable_type* header = chunk.header<ResTable_type>();
|
||||
const ResTable_type* header = chunk.header<ResTable_type, kResTableTypeMinSize>();
|
||||
|
||||
const size_t entry_count = dtohl(header->entryCount);
|
||||
if (entry_count > std::numeric_limits<uint16_t>::max()) {
|
||||
@@ -533,7 +533,7 @@ std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
|
||||
} break;
|
||||
|
||||
case RES_TABLE_TYPE_TYPE: {
|
||||
const ResTable_type* type = child_chunk.header<ResTable_type>();
|
||||
const ResTable_type* type = child_chunk.header<ResTable_type, kResTableTypeMinSize>();
|
||||
if (type == nullptr) {
|
||||
LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE is too small.";
|
||||
return {};
|
||||
|
||||
@@ -48,9 +48,9 @@ class Chunk {
|
||||
// Returns the size of the header. Caller need not worry about endianness.
|
||||
inline size_t header_size() const { return dtohs(device_chunk_->headerSize); }
|
||||
|
||||
template <typename T>
|
||||
template <typename T, size_t MinSize = sizeof(T)>
|
||||
inline const T* header() const {
|
||||
if (header_size() >= sizeof(T)) {
|
||||
if (header_size() >= MinSize) {
|
||||
return reinterpret_cast<const T*>(device_chunk_);
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
@@ -1391,11 +1391,20 @@ struct ResTable_type
|
||||
|
||||
// Offset from header where ResTable_entry data starts.
|
||||
uint32_t entriesStart;
|
||||
|
||||
// Configuration this collection of entries is designed for.
|
||||
|
||||
// Configuration this collection of entries is designed for. This must always be last.
|
||||
ResTable_config config;
|
||||
};
|
||||
|
||||
// The minimum size required to read any version of ResTable_type.
|
||||
constexpr size_t kResTableTypeMinSize =
|
||||
sizeof(ResTable_type) - sizeof(ResTable_config) + sizeof(ResTable_config::size);
|
||||
|
||||
// Assert that the ResTable_config is always the last field. This poses a problem for extending
|
||||
// ResTable_type in the future, as ResTable_config is variable (over different releases).
|
||||
static_assert(sizeof(ResTable_type) == offsetof(ResTable_type, config) + sizeof(ResTable_config),
|
||||
"ResTable_config must be last field in ResTable_type");
|
||||
|
||||
/**
|
||||
* An entry in a ResTable_type with the flag `FLAG_SPARSE` set.
|
||||
*/
|
||||
|
||||
@@ -313,7 +313,9 @@ bool BinaryResourceParser::ParseType(const ResourceTablePackage* package,
|
||||
return false;
|
||||
}
|
||||
|
||||
const ResTable_type* type = ConvertTo<ResTable_type>(chunk);
|
||||
// Specify a manual size, because ResTable_type contains ResTable_config, which changes
|
||||
// a lot and has its own code to handle variable size.
|
||||
const ResTable_type* type = ConvertTo<ResTable_type, kResTableTypeMinSize>(chunk);
|
||||
if (!type) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage(source_)
|
||||
<< "corrupt ResTable_type chunk");
|
||||
|
||||
@@ -78,9 +78,9 @@ class ResChunkPullParser {
|
||||
std::string error_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
template <typename T, size_t MinSize = sizeof(T)>
|
||||
inline static const T* ConvertTo(const android::ResChunk_header* chunk) {
|
||||
if (util::DeviceToHost16(chunk->headerSize) < sizeof(T)) {
|
||||
if (util::DeviceToHost16(chunk->headerSize) < MinSize) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<const T*>(chunk);
|
||||
|
||||
Reference in New Issue
Block a user