@@ -88,7 +88,9 @@ static bool VerifyResTableType(incfs::map_ptr<ResTable_type> header) {
88
88
// Make sure that there is enough room for the entry offsets.
89
89
const size_t offsets_offset = dtohs (header->header .headerSize );
90
90
const size_t entries_offset = dtohl (header->entriesStart );
91
- const size_t offsets_length = sizeof (uint32_t ) * entry_count;
91
+ const size_t offsets_length = header->flags & ResTable_type::FLAG_OFFSET16
92
+ ? sizeof (uint16_t ) * entry_count
93
+ : sizeof (uint32_t ) * entry_count;
92
94
93
95
if (offsets_offset > entries_offset || entries_offset - offsets_offset < offsets_length) {
94
96
LOG (ERROR) << " RES_TABLE_TYPE_TYPE entry offsets overlap actual entry data." ;
@@ -247,14 +249,13 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::GetEntryOffset(
247
249
// The configuration matches and is better than the previous selection.
248
250
// Find the entry value if it exists for this configuration.
249
251
const size_t entry_count = dtohl (type_chunk->entryCount );
250
- const size_t offsets_offset = dtohs (type_chunk->header .headerSize );
252
+ const auto offsets = type_chunk. offset ( dtohs (type_chunk->header .headerSize ) );
251
253
252
254
// Check if there is the desired entry in this type.
253
255
if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
254
256
// This is encoded as a sparse map, so perform a binary search.
255
257
bool error = false ;
256
- auto sparse_indices = type_chunk.offset (offsets_offset)
257
- .convert <ResTable_sparseTypeEntry>().iterator ();
258
+ auto sparse_indices = offsets.convert <ResTable_sparseTypeEntry>().iterator ();
258
259
auto sparse_indices_end = sparse_indices + entry_count;
259
260
auto result = std::lower_bound (sparse_indices, sparse_indices_end, entry_index,
260
261
[&error](const incfs::map_ptr<ResTable_sparseTypeEntry>& entry,
@@ -289,17 +290,26 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::GetEntryOffset(
289
290
return base::unexpected (std::nullopt);
290
291
}
291
292
292
- const auto entry_offset_ptr = type_chunk.offset (offsets_offset).convert <uint32_t >() + entry_index;
293
- if (UNLIKELY (!entry_offset_ptr)) {
294
- return base::unexpected (IOError::PAGES_MISSING);
293
+ uint32_t result;
294
+
295
+ if (type_chunk->flags & ResTable_type::FLAG_OFFSET16) {
296
+ const auto entry_offset_ptr = offsets.convert <uint16_t >() + entry_index;
297
+ if (UNLIKELY (!entry_offset_ptr)) {
298
+ return base::unexpected (IOError::PAGES_MISSING);
299
+ }
300
+ result = offset_from16 (entry_offset_ptr.value ());
301
+ } else {
302
+ const auto entry_offset_ptr = offsets.convert <uint32_t >() + entry_index;
303
+ if (UNLIKELY (!entry_offset_ptr)) {
304
+ return base::unexpected (IOError::PAGES_MISSING);
305
+ }
306
+ result = dtohl (entry_offset_ptr.value ());
295
307
}
296
308
297
- const uint32_t value = dtohl (entry_offset_ptr.value ());
298
- if (value == ResTable_type::NO_ENTRY) {
309
+ if (result == ResTable_type::NO_ENTRY) {
299
310
return base::unexpected (std::nullopt);
300
311
}
301
-
302
- return value;
312
+ return result;
303
313
}
304
314
305
315
base::expected<incfs::verified_map_ptr<ResTable_entry>, NullOrIOError>
@@ -382,24 +392,35 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName(
382
392
for (const auto & type_entry : type_spec->type_entries ) {
383
393
const incfs::verified_map_ptr<ResTable_type>& type = type_entry.type ;
384
394
385
- size_t entry_count = dtohl (type->entryCount );
386
- for (size_t entry_idx = 0 ; entry_idx < entry_count; entry_idx++) {
387
- auto entry_offset_ptr = type.offset (dtohs (type->header .headerSize )).convert <uint32_t >() +
388
- entry_idx;
389
- if (!entry_offset_ptr) {
390
- return base::unexpected (IOError::PAGES_MISSING);
391
- }
395
+ const size_t entry_count = dtohl (type->entryCount );
396
+ const auto entry_offsets = type.offset (dtohs (type->header .headerSize ));
392
397
398
+ for (size_t entry_idx = 0 ; entry_idx < entry_count; entry_idx++) {
393
399
uint32_t offset;
394
400
uint16_t res_idx;
395
401
if (type->flags & ResTable_type::FLAG_SPARSE) {
396
- auto sparse_entry = entry_offset_ptr.convert <ResTable_sparseTypeEntry>();
402
+ auto sparse_entry = entry_offsets.convert <ResTable_sparseTypeEntry>() + entry_idx;
403
+ if (!sparse_entry) {
404
+ return base::unexpected (IOError::PAGES_MISSING);
405
+ }
397
406
offset = dtohs (sparse_entry->offset ) * 4u ;
398
407
res_idx = dtohs (sparse_entry->idx );
408
+ } else if (type->flags & ResTable_type::FLAG_OFFSET16) {
409
+ auto entry = entry_offsets.convert <uint16_t >() + entry_idx;
410
+ if (!entry) {
411
+ return base::unexpected (IOError::PAGES_MISSING);
412
+ }
413
+ offset = offset_from16 (entry.value ());
414
+ res_idx = entry_idx;
399
415
} else {
400
- offset = dtohl (entry_offset_ptr.value ());
416
+ auto entry = entry_offsets.convert <uint32_t >() + entry_idx;
417
+ if (!entry) {
418
+ return base::unexpected (IOError::PAGES_MISSING);
419
+ }
420
+ offset = dtohl (entry.value ());
401
421
res_idx = entry_idx;
402
422
}
423
+
403
424
if (offset != ResTable_type::NO_ENTRY) {
404
425
auto entry = type.offset (dtohl (type->entriesStart ) + offset).convert <ResTable_entry>();
405
426
if (!entry) {
0 commit comments