Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a485aa6f authored by Eric Miao's avatar Eric Miao Committed by Android (Google) Code Review
Browse files

Merge "androidfw: Add support for compact resource entries"

parents 69ad733b 368cd19d
Loading
Loading
Loading
Loading
+12 −26
Original line number Original line Diff line number Diff line
@@ -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
@@ -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());
  }
  }
@@ -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(),
  };
  };
}
}
+15 −9
Original line number Original line Diff line number Diff line
@@ -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.";
@@ -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.";
@@ -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))) {
@@ -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)
@@ -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())) {
@@ -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(
@@ -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);
+18 −28
Original line number Original line Diff line number Diff line
@@ -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
@@ -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;


@@ -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;
@@ -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;
@@ -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;
    }
    }


@@ -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;
}
}
@@ -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;
@@ -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;
+3 −3
Original line number Original line Diff line number Diff line
@@ -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;
+4 −4
Original line number Original line Diff line number Diff line
@@ -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