diff --git a/cmds/idmap2/idmap2/CommandUtils.cpp b/cmds/idmap2/idmap2/CommandUtils.cpp index 8f5845bf2e53e..45f37962331b3 100644 --- a/cmds/idmap2/idmap2/CommandUtils.cpp +++ b/cmds/idmap2/idmap2/CommandUtils.cpp @@ -39,8 +39,8 @@ Result Verify(const std::string& idmap_path, const std::string& target_pat return Error("failed to parse idmap header"); } - const auto header_ok = header->IsUpToDate(target_path.c_str(), overlay_path.c_str(), - fulfilled_policies, enforce_overlayable); + const auto header_ok = + header->IsUpToDate(target_path, overlay_path, fulfilled_policies, enforce_overlayable); if (!header_ok) { return Error(header_ok.GetError(), "idmap not up to date"); } diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index 437180d3d1bef..64e49307c0df5 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -188,29 +188,27 @@ Result Lookup(const std::vector& args) { } if (i == 0) { - target_path = idmap_header->GetTargetPath().to_string(); + target_path = idmap_header->GetTargetPath(); auto target_apk = ApkAssets::Load(target_path); if (!target_apk) { return Error("failed to read target apk from %s", target_path.c_str()); } apk_assets.push_back(std::move(target_apk)); - auto manifest_info = ExtractOverlayManifestInfo(idmap_header->GetOverlayPath().to_string(), - true /* assert_overlay */); + auto manifest_info = + ExtractOverlayManifestInfo(idmap_header->GetOverlayPath(), true /* assert_overlay */); if (!manifest_info) { return manifest_info.GetError(); } target_package_name = (*manifest_info).target_package; } else if (target_path != idmap_header->GetTargetPath()) { return Error("different target APKs (expected target APK %s but %s has target APK %s)", - target_path.c_str(), idmap_path.c_str(), - idmap_header->GetTargetPath().to_string().c_str()); + target_path.c_str(), idmap_path.c_str(), idmap_header->GetTargetPath().c_str()); } auto overlay_apk = ApkAssets::LoadOverlay(idmap_path); if (!overlay_apk) { - return Error("failed to read overlay apk from %s", - idmap_header->GetOverlayPath().to_string().c_str()); + return Error("failed to read overlay apk from %s", idmap_header->GetOverlayPath().c_str()); } apk_assets.push_back(std::move(overlay_apk)); } diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index 15e22a3410cfa..8a7272c073b94 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -156,7 +156,7 @@ Status Idmap2Service::verifyIdmap(const std::string& target_apk_path, } auto up_to_date = - header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), target_crc, overlay_crc, + header->IsUpToDate(target_apk_path overlay_apk_path, target_crc, overlay_crc, ConvertAidlArgToPolicyBitmask(fulfilled_policies), enforce_overlayable); *_aidl_return = static_cast(up_to_date); diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h index bf31cbf8d4f73..5e189f2c13404 100644 --- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h +++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h @@ -39,7 +39,6 @@ class BinaryStreamVisitor : public Visitor { void Write8(uint8_t value); void Write16(uint16_t value); void Write32(uint32_t value); - void WriteString256(const StringPiece& value); void WriteString(const StringPiece& value); std::ostream& stream_; }; diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index a35fad9d686c0..3163e40a7bffa 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -37,13 +37,12 @@ * overlay_entry_count := * overlay_id := * overlay_package_id := - * overlay_path := string256 + * overlay_path := string * padding(n) := [n] * Res_value::size := * Res_value::type := * Res_value::value := * string := + padding(n) - * string256 := [256] * string_pool := string * string_pool_index := * string_pool_length := @@ -52,7 +51,7 @@ * target_inline_entry_count := * target_id := * target_package_id := - * target_path := string256 + * target_path := string * value_type := * value_data := * version := @@ -87,10 +86,6 @@ static constexpr const uint32_t kIdmapMagic = android::kIdmapMagic; // current version of the idmap binary format; must be incremented when the format is changed static constexpr const uint32_t kIdmapCurrentVersion = android::kIdmapCurrentVersion; -// strings in the idmap are encoded char arrays of length 'kIdmapStringLength' (including mandatory -// terminating null) -static constexpr const size_t kIdmapStringLength = 256; - // Retrieves a crc generated using all of the files within the zip that can affect idmap generation. Result GetPackageCrc(const ZipFile& zip_info); @@ -122,26 +117,26 @@ class IdmapHeader { return enforce_overlayable_; } - inline StringPiece GetTargetPath() const { - return StringPiece(target_path_); + const std::string& GetTargetPath() const { + return target_path_; } - inline StringPiece GetOverlayPath() const { - return StringPiece(overlay_path_); + const std::string& GetOverlayPath() const { + return overlay_path_; } - inline const std::string& GetDebugInfo() const { + const std::string& GetDebugInfo() const { return debug_info_; } // Invariant: anytime the idmap data encoding is changed, the idmap version // field *must* be incremented. Because of this, we know that if the idmap // header is up-to-date the entire file is up-to-date. - Result IsUpToDate(const char* target_path, const char* overlay_path, + Result IsUpToDate(const std::string& target_path, const std::string& overlay_path, + PolicyBitmask fulfilled_policies, bool enforce_overlayable) const; + Result IsUpToDate(const std::string& target_path, const std::string& overlay_path, + uint32_t target_crc, uint32_t overlay_crc, PolicyBitmask fulfilled_policies, bool enforce_overlayable) const; - Result IsUpToDate(const char* target_path, const char* overlay_path, uint32_t target_crc, - uint32_t overlay_crc, PolicyBitmask fulfilled_policies, - bool enforce_overlayable) const; void accept(Visitor* v) const; @@ -155,8 +150,8 @@ class IdmapHeader { uint32_t overlay_crc_; uint32_t fulfilled_policies_; bool enforce_overlayable_; - char target_path_[kIdmapStringLength]; - char overlay_path_[kIdmapStringLength]; + std::string target_path_; + std::string overlay_path_; std::string debug_info_; friend Idmap; @@ -291,8 +286,7 @@ class Idmap { void accept(Visitor* v) const; private: - Idmap() { - } + Idmap() = default; std::unique_ptr header_; std::vector> data_; @@ -302,8 +296,7 @@ class Idmap { class Visitor { public: - virtual ~Visitor() { - } + virtual ~Visitor() = default; virtual void visit(const Idmap& idmap) = 0; virtual void visit(const IdmapHeader& header) = 0; virtual void visit(const IdmapData& data) = 0; diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h index 58edc99715fd0..45835164ef8e8 100644 --- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h +++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h @@ -44,7 +44,9 @@ class RawPrintVisitor : public Visitor { void print(uint8_t value, const char* fmt, ...); void print(uint16_t value, const char* fmt, ...); void print(uint32_t value, const char* fmt, ...); - void print(const std::string& value, size_t encoded_size, const char* fmt, ...); + void print(const std::string& value, bool print_value, const char* fmt, ...); + void align(); + void pad(size_t padding); std::ostream& stream_; std::vector> apk_assets_; diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp index 726f6c5c2c99a..5db09baca5d5a 100644 --- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp +++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp @@ -38,13 +38,6 @@ void BinaryStreamVisitor::Write32(uint32_t value) { stream_.write(reinterpret_cast(&x), sizeof(uint32_t)); } -void BinaryStreamVisitor::WriteString256(const StringPiece& value) { - char buf[kIdmapStringLength]; - memset(buf, 0, sizeof(buf)); - memcpy(buf, value.data(), std::min(value.size(), sizeof(buf))); - stream_.write(buf, sizeof(buf)); -} - void BinaryStreamVisitor::WriteString(const StringPiece& value) { // pad with null to nearest word boundary; size_t padding_size = CalculatePadding(value.size()); @@ -64,8 +57,8 @@ void BinaryStreamVisitor::visit(const IdmapHeader& header) { Write32(header.GetOverlayCrc()); Write32(header.GetFulfilledPolicies()); Write32(static_cast(header.GetEnforceOverlayable())); - WriteString256(header.GetTargetPath()); - WriteString256(header.GetOverlayPath()); + WriteString(header.GetTargetPath()); + WriteString(header.GetOverlayPath()); WriteString(header.GetDebugInfo()); } diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index 1129413584b2a..4745cc6cdc331 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -69,38 +69,26 @@ bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) { return false; } -// a string is encoded as a kIdmapStringLength char array; the array is always null-terminated -bool WARN_UNUSED ReadString256(std::istream& stream, char out[kIdmapStringLength]) { - char buf[kIdmapStringLength]; - memset(buf, 0, sizeof(buf)); - if (!stream.read(buf, sizeof(buf))) { - return false; - } - if (buf[sizeof(buf) - 1] != '\0') { - return false; - } - memcpy(out, buf, sizeof(buf)); - return true; -} - -Result ReadString(std::istream& stream) { +bool WARN_UNUSED ReadString(std::istream& stream, std::string* out) { uint32_t size; if (!Read32(stream, &size)) { - return Error("failed to read string size"); + return false; } if (size == 0) { - return std::string(""); + *out = ""; + return true; } std::string buf(size, '\0'); if (!stream.read(buf.data(), size)) { - return Error("failed to read string of size %u", size); + return false; } uint32_t padding_size = CalculatePadding(size); std::string padding(padding_size, '\0'); if (!stream.read(padding.data(), padding_size)) { - return Error("failed to read string padding of size %u", padding_size); + return false; } - return buf; + *out = buf; + return true; } } // namespace @@ -119,28 +107,23 @@ std::unique_ptr IdmapHeader::FromBinaryStream(std::istream& s if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) || !Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) || !Read32(stream, &idmap_header->fulfilled_policies_) || - !Read32(stream, &enforce_overlayable) || !ReadString256(stream, idmap_header->target_path_) || - !ReadString256(stream, idmap_header->overlay_path_)) { + !Read32(stream, &enforce_overlayable) || !ReadString(stream, &idmap_header->target_path_) || + !ReadString(stream, &idmap_header->overlay_path_) || + !ReadString(stream, &idmap_header->debug_info_)) { return nullptr; } idmap_header->enforce_overlayable_ = enforce_overlayable != 0U; - - auto debug_str = ReadString(stream); - if (!debug_str) { - return nullptr; - } - idmap_header->debug_info_ = std::move(*debug_str); - return std::move(idmap_header); } -Result IdmapHeader::IsUpToDate(const char* target_path, const char* overlay_path, +Result IdmapHeader::IsUpToDate(const std::string& target_path, + const std::string& overlay_path, PolicyBitmask fulfilled_policies, bool enforce_overlayable) const { const std::unique_ptr target_zip = ZipFile::Open(target_path); if (!target_zip) { - return Error("failed to open target %s", target_path); + return Error("failed to open target %s", target_path.c_str()); } const Result target_crc = GetPackageCrc(*target_zip); @@ -150,7 +133,7 @@ Result IdmapHeader::IsUpToDate(const char* target_path, const char* overla const std::unique_ptr overlay_zip = ZipFile::Open(overlay_path); if (!overlay_zip) { - return Error("failed to overlay target %s", overlay_path); + return Error("failed to overlay target %s", overlay_path.c_str()); } const Result overlay_crc = GetPackageCrc(*overlay_zip); @@ -162,9 +145,9 @@ Result IdmapHeader::IsUpToDate(const char* target_path, const char* overla enforce_overlayable); } -Result IdmapHeader::IsUpToDate(const char* target_path, const char* overlay_path, - uint32_t target_crc, uint32_t overlay_crc, - PolicyBitmask fulfilled_policies, +Result IdmapHeader::IsUpToDate(const std::string& target_path, + const std::string& overlay_path, uint32_t target_crc, + uint32_t overlay_crc, PolicyBitmask fulfilled_policies, bool enforce_overlayable) const { if (magic_ != kIdmapMagic) { return Error("bad magic: actual 0x%08x, expected 0x%08x", magic_, kIdmapMagic); @@ -194,14 +177,14 @@ Result IdmapHeader::IsUpToDate(const char* target_path, const char* overla enforce_overlayable ? "true" : "false", enforce_overlayable_ ? "true" : "false"); } - if (strcmp(target_path, target_path_) != 0) { - return Error("bad target path: idmap version %s, file system version %s", target_path, - target_path_); + if (target_path != target_path_) { + return Error("bad target path: idmap version %s, file system version %s", target_path.c_str(), + target_path_.c_str()); } - if (strcmp(overlay_path, overlay_path_) != 0) { - return Error("bad overlay path: idmap version %s, file system version %s", overlay_path, - overlay_path_); + if (overlay_path != overlay_path_) { + return Error("bad overlay path: idmap version %s, file system version %s", overlay_path.c_str(), + overlay_path_.c_str()); } return Unit{}; @@ -262,12 +245,9 @@ std::unique_ptr IdmapData::FromBinaryStream(std::istream& strea } // Read raw string pool bytes. - auto string_pool_data = ReadString(stream); - if (!string_pool_data) { + if (!ReadString(stream, &data->string_pool_data_)) { return nullptr; } - data->string_pool_data_ = std::move(*string_pool_data); - return std::move(data); } @@ -368,23 +348,10 @@ Result> Idmap::FromApkAssets(const ApkAssets& targe return Error(crc.GetError(), "failed to get zip CRC for overlay"); } header->overlay_crc_ = *crc; - header->fulfilled_policies_ = fulfilled_policies; header->enforce_overlayable_ = enforce_overlayable; - - if (target_apk_path.size() > sizeof(header->target_path_)) { - return Error("target apk path \"%s\" longer than maximum size %zu", target_apk_path.c_str(), - sizeof(header->target_path_)); - } - memset(header->target_path_, 0, sizeof(header->target_path_)); - memcpy(header->target_path_, target_apk_path.data(), target_apk_path.size()); - - if (overlay_apk_path.size() > sizeof(header->overlay_path_)) { - return Error("overlay apk path \"%s\" longer than maximum size %zu", overlay_apk_path.c_str(), - sizeof(header->target_path_)); - } - memset(header->overlay_path_, 0, sizeof(header->overlay_path_)); - memcpy(header->overlay_path_, overlay_apk_path.data(), overlay_apk_path.size()); + header->target_path_ = target_apk_path; + header->overlay_path_ = overlay_apk_path; auto overlay_info = utils::ExtractOverlayManifestInfo(overlay_apk_path); if (!overlay_info) { diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp index 3037a791328e3..f56d3d21e25b6 100644 --- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp @@ -49,12 +49,12 @@ void PrettyPrintVisitor::visit(const IdmapHeader& header) { } } - if (auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string())) { + if (auto target_apk_ = ApkAssets::Load(header.GetTargetPath())) { target_am_.SetApkAssets({target_apk_.get()}); apk_assets_.push_back(std::move(target_apk_)); } - if (auto overlay_apk = ApkAssets::Load(header.GetOverlayPath().to_string())) { + if (auto overlay_apk = ApkAssets::Load(header.GetOverlayPath())) { overlay_am_.SetApkAssets({overlay_apk.get()}); apk_assets_.push_back(std::move(overlay_apk)); } diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp index 82f5d26cbbb31..d7f073944542e 100644 --- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp @@ -43,20 +43,17 @@ void RawPrintVisitor::visit(const IdmapHeader& header) { print(header.GetFulfilledPolicies(), "fulfilled policies: %s", PoliciesToDebugString(header.GetFulfilledPolicies()).c_str()); print(static_cast(header.GetEnforceOverlayable()), "enforce overlayable"); - print(header.GetTargetPath().to_string(), kIdmapStringLength, "target path"); - print(header.GetOverlayPath().to_string(), kIdmapStringLength, "overlay path"); + print(header.GetTargetPath(), true /* print_value */, "target path"); + print(header.GetOverlayPath(), true /* print_value */, "overlay path"); + print(header.GetDebugInfo(), false /* print_value */, "debug info"); - uint32_t debug_info_size = header.GetDebugInfo().size(); - print(debug_info_size, "debug info size"); - print("...", debug_info_size + CalculatePadding(debug_info_size), "debug info"); - - auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string()); + auto target_apk_ = ApkAssets::Load(header.GetTargetPath()); if (target_apk_) { target_am_.SetApkAssets({target_apk_.get()}); apk_assets_.push_back(std::move(target_apk_)); } - auto overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string()); + auto overlay_apk_ = ApkAssets::Load(header.GetOverlayPath()); if (overlay_apk_) { overlay_am_.SetApkAssets({overlay_apk_.get()}); apk_assets_.push_back(std::move(overlay_apk_)); @@ -100,7 +97,7 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { print(target_entry.target_id, "target id"); } - print("...", sizeof(Res_value::size) + sizeof(Res_value::res0), "padding"); + pad(sizeof(Res_value::size) + sizeof(Res_value::res0)); print(target_entry.value.data_type, "type: %s", utils::DataTypeToString(target_entry.value.data_type).data()); @@ -143,15 +140,13 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { } } - uint32_t string_pool_size = data.GetStringPoolData().size(); - print(string_pool_size, "string pool size"); - print("...", string_pool_size + CalculatePadding(string_pool_size), "string pool"); + print(data.GetStringPoolData(), false /* print_value */, "string pool"); } void RawPrintVisitor::visit(const IdmapData::Header& header) { print(header.GetTargetPackageId(), "target package id"); print(header.GetOverlayPackageId(), "overlay package id"); - print("...", sizeof(Idmap_data_header::p0), "padding"); + align(); print(header.GetTargetEntryCount(), "target entry count"); print(header.GetTargetInlineEntryCount(), "target inline entry count"); print(header.GetOverlayEntryCount(), "overlay entry count"); @@ -168,7 +163,6 @@ void RawPrintVisitor::print(uint8_t value, const char* fmt, ...) { stream_ << base::StringPrintf("%08zx: %02x", offset_, value) << " " << comment << std::endl; - offset_ += sizeof(uint8_t); } @@ -181,7 +175,6 @@ void RawPrintVisitor::print(uint16_t value, const char* fmt, ...) { va_end(ap); stream_ << base::StringPrintf("%08zx: %04x", offset_, value) << " " << comment << std::endl; - offset_ += sizeof(uint16_t); } @@ -194,22 +187,35 @@ void RawPrintVisitor::print(uint32_t value, const char* fmt, ...) { va_end(ap); stream_ << base::StringPrintf("%08zx: %08x", offset_, value) << " " << comment << std::endl; - offset_ += sizeof(uint32_t); } // NOLINTNEXTLINE(cert-dcl50-cpp) -void RawPrintVisitor::print(const std::string& value, size_t encoded_size, const char* fmt, ...) { +void RawPrintVisitor::print(const std::string& value, bool print_value, const char* fmt, ...) { va_list ap; va_start(ap, fmt); std::string comment; base::StringAppendV(&comment, fmt, ap); va_end(ap); - stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment << ": " << value - << std::endl; + stream_ << base::StringPrintf("%08zx: %08x", offset_, (uint32_t)value.size()) << " " << comment + << " size" << std::endl; + offset_ += sizeof(uint32_t); - offset_ += encoded_size; + stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment; + offset_ += value.size() + CalculatePadding(value.size()); + + if (print_value) { + stream_ << ": " << value; + } + stream_ << std::endl; } +void RawPrintVisitor::align() { + offset_ += CalculatePadding(offset_); +} + +void RawPrintVisitor::pad(size_t padding) { + offset_ += padding; +} } // namespace android::idmap2 diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index d777cbfa9a14c..9abb9e458902a 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -230,8 +230,8 @@ Result ResourceMapping::CreateResourceMappingLegacy( base::StringPrintf("%s:%s", target_package->GetPackageName().c_str(), name->c_str()); auto target_resource_result = target_am->GetResourceId(full_name); if (!target_resource_result.has_value()) { - log_info.Warning(LogMessage() << "failed to find resource \"" << full_name - << "\" in target resources"); + log_info.Warning(LogMessage() + << "failed to find resource \"" << full_name << "\" in target resources"); continue; } diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 9b42a2781b58f..7be1602ccf40d 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -35,7 +35,6 @@ #include "idmap2/LogInfo.h" using android::Res_value; -using ::testing::IsNull; using ::testing::NotNull; using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; @@ -66,29 +65,18 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) { std::unique_ptr header = IdmapHeader::FromBinaryStream(stream); ASSERT_THAT(header, NotNull()); ASSERT_EQ(header->GetMagic(), 0x504d4449U); - ASSERT_EQ(header->GetVersion(), 0x05U); + ASSERT_EQ(header->GetVersion(), 0x06U); ASSERT_EQ(header->GetTargetCrc(), 0x1234U); ASSERT_EQ(header->GetOverlayCrc(), 0x5678U); ASSERT_EQ(header->GetFulfilledPolicies(), 0x11); ASSERT_EQ(header->GetEnforceOverlayable(), true); - ASSERT_EQ(header->GetTargetPath().to_string(), "targetX.apk"); - ASSERT_EQ(header->GetOverlayPath().to_string(), "overlayX.apk"); + ASSERT_EQ(header->GetTargetPath(), "targetX.apk"); + ASSERT_EQ(header->GetOverlayPath(), "overlayX.apk"); ASSERT_EQ(header->GetDebugInfo(), "debug"); } -TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) { - std::string raw(reinterpret_cast(idmap_raw_data), idmap_raw_data_len); - // overwrite the target path string, including the terminating null, with '.' - for (size_t i = 0x18; i < 0x118; i++) { - raw[i] = '.'; - } - std::istringstream stream(raw); - std::unique_ptr header = IdmapHeader::FromBinaryStream(stream); - ASSERT_THAT(header, IsNull()); -} - TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) { - const size_t offset = 0x224; + const size_t offset = idmap_raw_data_offset; std::string raw(reinterpret_cast(idmap_raw_data + offset), idmap_raw_data_len - offset); std::istringstream stream(raw); @@ -100,7 +88,7 @@ TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) { } TEST(IdmapTests, CreateIdmapDataFromBinaryStream) { - const size_t offset = 0x224; + const size_t offset = idmap_raw_data_offset; std::string raw(reinterpret_cast(idmap_raw_data + offset), idmap_raw_data_len - offset); std::istringstream stream(raw); @@ -136,13 +124,13 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x06U); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U); ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), 0x11); ASSERT_EQ(idmap->GetHeader()->GetEnforceOverlayable(), true); - ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "targetX.apk"); - ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlayX.apk"); + ASSERT_EQ(idmap->GetHeader()->GetTargetPath(), idmap_raw_data_target_path); + ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), idmap_raw_data_overlay_path); const std::vector>& dataBlocks = idmap->GetData(); ASSERT_EQ(dataBlocks.size(), 1U); @@ -195,12 +183,12 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x06U); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC); ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC); ASSERT_EQ(idmap->GetHeader()->GetEnforceOverlayable(), true); - ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path); + ASSERT_EQ(idmap->GetHeader()->GetTargetPath(), target_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); } @@ -370,38 +358,19 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) { ASSERT_EQ(overlay_entries.size(), 0U); } -TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) { - std::string target_apk_path(GetTestDataPath()); - for (int i = 0; i < 32; i++) { - target_apk_path += "/target/../"; - } - target_apk_path += "/target/target.apk"; - ASSERT_GT(target_apk_path.size(), kIdmapStringLength); - std::unique_ptr target_apk = ApkAssets::Load(target_apk_path); - ASSERT_THAT(target_apk, NotNull()); - - const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk"); - std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); - ASSERT_THAT(overlay_apk, NotNull()); - - const auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, - /* enforce_overlayable */ true); - ASSERT_FALSE(result); -} - TEST(IdmapTests, IdmapHeaderIsUpToDate) { fclose(stderr); // silence expected warnings from libandroidfw - const std::string target_apk_path(GetTestDataPath() + "/target/target.apk"); - std::unique_ptr target_apk = ApkAssets::Load(target_apk_path); - ASSERT_THAT(target_apk, NotNull()); + const std::string target_apk_path = idmap_raw_data_target_path; + const std::string overlay_apk_path = idmap_raw_data_overlay_path; + const PolicyBitmask policies = idmap_raw_data_policies; + const uint32_t target_crc = idmap_raw_data_target_crc; + const uint32_t overlay_crc = idmap_raw_data_overlay_crc; - const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk"); - std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); - ASSERT_THAT(overlay_apk, NotNull()); + std::string raw(reinterpret_cast(idmap_raw_data), idmap_raw_data_len); + std::istringstream raw_stream(raw); - auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, - /* enforce_overlayable */ true); + auto result = Idmap::FromBinaryStream(raw_stream); ASSERT_TRUE(result); const auto idmap = std::move(*result); @@ -411,8 +380,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { std::unique_ptr header = IdmapHeader::FromBinaryStream(stream); ASSERT_THAT(header, NotNull()); - ASSERT_TRUE(header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_TRUE(header->IsUpToDate(target_apk_path, overlay_apk_path, idmap_raw_data_target_crc, + overlay_crc, policies, /* enforce_overlayable */ true)); // magic: bytes (0x0, 0x03) std::string bad_magic_string(stream.str()); @@ -425,8 +394,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_magic_stream); ASSERT_THAT(bad_magic_header, NotNull()); ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, /* enforce_overlayable */ true)); // version: bytes (0x4, 0x07) std::string bad_version_string(stream.str()); @@ -439,8 +408,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_version_stream); ASSERT_THAT(bad_version_header, NotNull()); ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, /* enforce_overlayable */ true)); // target crc: bytes (0x8, 0xb) std::string bad_target_crc_string(stream.str()); @@ -453,8 +422,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_target_crc_stream); ASSERT_THAT(bad_target_crc_header, NotNull()); ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, /* enforce_overlayable */ true)); // overlay crc: bytes (0xc, 0xf) std::string bad_overlay_crc_string(stream.str()); @@ -467,8 +436,8 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_overlay_crc_stream); ASSERT_THAT(bad_overlay_crc_header, NotNull()); ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, /* enforce_overlayable */ true)); // fulfilled policy: bytes (0x10, 0x13) std::string bad_policy_string(stream.str()); @@ -481,8 +450,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_policy_stream); ASSERT_THAT(bad_policy_header, NotNull()); ASSERT_NE(header->GetFulfilledPolicies(), bad_policy_header->GetFulfilledPolicies()); - ASSERT_FALSE(bad_policy_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_policy_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, + /* enforce_overlayable */ true)); // enforce overlayable: bytes (0x14) std::string bad_enforce_string(stream.str()); @@ -492,30 +462,32 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_enforce_stream); ASSERT_THAT(bad_enforce_header, NotNull()); ASSERT_NE(header->GetEnforceOverlayable(), bad_enforce_header->GetEnforceOverlayable()); - ASSERT_FALSE(bad_enforce_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_enforce_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, + /* enforce_overlayable */ true)); - // target path: bytes (0x18, 0x117) + // target path: bytes (0x1c, 0x27) std::string bad_target_path_string(stream.str()); - bad_target_path_string[0x18] = '\0'; + bad_target_path_string[0x1c] = '\0'; std::stringstream bad_target_path_stream(bad_target_path_string); std::unique_ptr bad_target_path_header = IdmapHeader::FromBinaryStream(bad_target_path_stream); ASSERT_THAT(bad_target_path_header, NotNull()); ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, /* enforce_overlayable */ true)); - // overlay path: bytes (0x118, 0x217) + // overlay path: bytes (0x2c, 0x37) std::string bad_overlay_path_string(stream.str()); - bad_overlay_path_string[0x118] = '\0'; + bad_overlay_path_string[0x33] = '\0'; std::stringstream bad_overlay_path_stream(bad_overlay_path_string); std::unique_ptr bad_overlay_path_header = IdmapHeader::FromBinaryStream(bad_overlay_path_stream); ASSERT_THAT(bad_overlay_path_header, NotNull()); ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), - PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); + ASSERT_FALSE(bad_overlay_path_header->IsUpToDate(target_apk_path, overlay_apk_path, target_crc, + overlay_crc, policies, + /* enforce_overlayable */ true)); } class TestVisitor : public Visitor { diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index 95bd94733ab37..b7ea22aa4a2e9 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -65,7 +65,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000005 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000006 version\n", stream.str()); ASSERT_CONTAINS_REGEX( StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING), stream.str()); @@ -85,7 +85,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "000000b4 string pool size\n", stream.str()); - ASSERT_CONTAINS_REGEX("000002bc: ........ string pool: ...\n", stream.str()); + ASSERT_CONTAINS_REGEX("000001bc: ........ string pool\n", stream.str()); } TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { @@ -102,7 +102,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000005 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000006 version\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str()); @@ -121,7 +121,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 string pool size\n", stream.str()); - ASSERT_CONTAINS_REGEX("00000278: ........ string pool: ...\n", stream.str()); + ASSERT_CONTAINS_REGEX("00000098: ........ string pool\n", stream.str()); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h index d0a8e3db8ecae..5c934a33ebb66 100644 --- a/cmds/idmap2/tests/TestHelpers.h +++ b/cmds/idmap2/tests/TestHelpers.h @@ -30,7 +30,7 @@ const unsigned char idmap_raw_data[] = { 0x49, 0x44, 0x4d, 0x50, // 0x4: version - 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, // 0x8: target crc 0x34, 0x12, 0x00, 0x00, @@ -44,125 +44,107 @@ const unsigned char idmap_raw_data[] = { // 0x14: enforce overlayable 0x01, 0x00, 0x00, 0x00, - // 0x18: target path "targetX.apk" - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 0x18: target path length + 0x0b, 0x00, 0x00, 0x00, - // 0x118: overlay path "overlayX.apk" - 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 0x1c: target path "targetX.apk" + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, - // 0x218: debug string + // 0x28: overlay path length + 0x0c, 0x00, 0x00, 0x00, + + // 0x2c: overlay path "overlayX.apk" + 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, + + // 0x38: debug string // string length, 0x05, 0x00, 0x00, 0x00, - // 0x21c string contents "debug\0\0\0" (padded to word alignment) + // 0x3c string contents "debug\0\0\0" (padded to word alignment) 0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00, // DATA HEADER - // 0x224: target_package_id + // 0x44: target_package_id 0x7f, - // 0x225: overlay_package_id + // 0x45: overlay_package_id 0x7f, - // 0x226: padding + // 0x46: padding 0x00, 0x00, - // 0x228: target_entry_count + // 0x48: target_entry_count 0x03, 0x00, 0x00, 0x00, - // 0x22c: target_inline_entry_count + // 0x4c: target_inline_entry_count 0x01, 0x00, 0x00, 0x00, - // 0x230: overlay_entry_count + // 0x50: overlay_entry_count 0x03, 0x00, 0x00, 0x00, - // 0x234: string_pool_offset + // 0x54: string_pool_offset 0x00, 0x00, 0x00, 0x00, // TARGET ENTRIES - // 0x238: target id (0x7f020000) + // 0x58: target id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x23c: overlay_id (0x7f020000) + // 0x5c: overlay_id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x240: target id (0x7f030000) + // 0x60: target id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x244: overlay_id (0x7f030000) + // 0x64: overlay_id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x248: target id (0x7f030002) + // 0x68: target id (0x7f030002) 0x02, 0x00, 0x03, 0x7f, - // 0x24c: overlay_id (0x7f030001) + // 0x6c: overlay_id (0x7f030001) 0x01, 0x00, 0x03, 0x7f, // INLINE TARGET ENTRIES - // 0x250: target_id + // 0x70: target_id 0x00, 0x00, 0x04, 0x7f, - // 0x254: Res_value::size (value ignored by idmap) + // 0x74: Res_value::size (value ignored by idmap) 0x08, 0x00, - // 0x256: Res_value::res0 (value ignored by idmap) + // 0x77: Res_value::res0 (value ignored by idmap) 0x00, - // 0x257: Res_value::dataType (TYPE_INT_HEX) + // 0x78: Res_value::dataType (TYPE_INT_HEX) 0x11, - // 0x258: Res_value::data + // 0x7c: Res_value::data 0x78, 0x56, 0x34, 0x12, // OVERLAY ENTRIES - // 0x25c: 0x7f020000 -> 0x7f020000 + // 0x80: 0x7f020000 -> 0x7f020000 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f, - // 0x264: 0x7f030000 -> 0x7f030000 + // 0x88: 0x7f030000 -> 0x7f030000 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f, - // 0x26c: 0x7f030001 -> 0x7f030002 + // 0x90: 0x7f030001 -> 0x7f030002 0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f, - // 0x274: string pool + // 0x94: string pool // string length, 0x04, 0x00, 0x00, 0x00, - // 0x278 string contents "test" (padded to word alignment) + // 0x98 string contents "test" 0x74, 0x65, 0x73, 0x74}; -const unsigned int idmap_raw_data_len = 0x27c; +const unsigned int idmap_raw_data_len = 0x9c; +const unsigned int idmap_raw_data_offset = 0x44; +const unsigned int idmap_raw_data_target_crc = 0x1234; +const unsigned int idmap_raw_data_overlay_crc = 0x5678; +const unsigned int idmap_raw_data_policies = 0x11; +inline const std::string idmap_raw_data_target_path = "targetX.apk"; +inline const std::string idmap_raw_data_overlay_path = "overlayX.apk"; std::string GetTestDataPath(); diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index cb56a5172a455..011a0de8031f8 100755 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -385,7 +385,7 @@ std::unique_ptr ApkAssets::LoadOverlay(const std::string& idmap return {}; } - auto overlay_path = loaded_idmap->OverlayApkPath(); + auto overlay_path = std::string(loaded_idmap->OverlayApkPath()); auto assets = ZipAssetsProvider::Create(overlay_path); return (assets) ? LoadImpl(std::move(assets), overlay_path, flags | PROPERTY_OVERLAY, nullptr /* override_asset */, std::move(idmap_asset), diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index bec80a7d605eb..3f0600040139c 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -157,7 +157,8 @@ void AssetManager2::BuildDynamicRefTable() { // The target package must precede the overlay package in the apk assets paths in order // to take effect. const auto& loaded_idmap = apk_assets->GetLoadedIdmap(); - auto target_package_iter = apk_assets_package_ids.find(loaded_idmap->TargetApkPath()); + auto target_package_iter = apk_assets_package_ids.find( + std::string(loaded_idmap->TargetApkPath())); if (target_package_iter == apk_assets_package_ids.end()) { LOG(INFO) << "failed to find target package for overlay " << loaded_idmap->OverlayApkPath(); diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp index a613095141432..68844be6d14a5 100644 --- a/libs/androidfw/Idmap.cpp +++ b/libs/androidfw/Idmap.cpp @@ -36,13 +36,51 @@ using ::android::base::StringPrintf; namespace android { -uint32_t round_to_4_bytes(uint32_t size) { - return size + (4U - (size % 4U)) % 4U; -} +// See frameworks/base/cmds/idmap2/include/idmap2/Idmap.h for full idmap file format specification. +struct Idmap_header { + // Always 0x504D4449 ('IDMP') + uint32_t magic; + uint32_t version; -size_t Idmap_header::Size() const { - return sizeof(Idmap_header) + sizeof(uint8_t) * round_to_4_bytes(dtohl(debug_info_size)); -} + uint32_t target_crc32; + uint32_t overlay_crc32; + + uint32_t fulfilled_policies; + uint32_t enforce_overlayable; + + // overlay_path, target_path, and other string values encoded in the idmap header and read and + // stored in separate structures. This allows the idmap header data to be casted to this struct + // without having to read/store each header entry separately. +}; + +struct Idmap_data_header { + uint8_t target_package_id; + uint8_t overlay_package_id; + + // Padding to ensure 4 byte alignment for target_entry_count + uint16_t p0; + + uint32_t target_entry_count; + uint32_t target_inline_entry_count; + uint32_t overlay_entry_count; + + uint32_t string_pool_index_offset; +}; + +struct Idmap_target_entry { + uint32_t target_id; + uint32_t overlay_id; +}; + +struct Idmap_target_entry_inline { + uint32_t target_id; + Res_value value; +}; + +struct Idmap_overlay_entry { + uint32_t overlay_id; + uint32_t target_id; +}; OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap) : data_header_(loaded_idmap->data_header_), @@ -155,140 +193,132 @@ IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const { return {}; } -static bool is_word_aligned(const void* data) { - return (reinterpret_cast(data) & 0x03U) == 0U; +namespace { +template +const T* ReadType(const uint8_t** in_out_data_ptr, size_t* in_out_size, const std::string& label, + size_t count = 1) { + if (!util::IsFourByteAligned(*in_out_data_ptr)) { + LOG(ERROR) << "Idmap " << label << " is not word aligned."; + return {}; + } + if ((*in_out_size / sizeof(T)) < count) { + LOG(ERROR) << "Idmap too small for the number of " << label << " entries (" + << count << ")."; + return nullptr; + } + auto data_ptr = *in_out_data_ptr; + const size_t read_size = sizeof(T) * count; + *in_out_data_ptr += read_size; + *in_out_size -= read_size; + return reinterpret_cast(data_ptr); } -static bool IsValidIdmapHeader(const StringPiece& data) { - if (!is_word_aligned(data.data())) { - LOG(ERROR) << "Idmap header is not word aligned."; - return false; +std::optional ReadString(const uint8_t** in_out_data_ptr, size_t* in_out_size, + const std::string& label) { + const auto* len = ReadType(in_out_data_ptr, in_out_size, label + " length"); + if (len == nullptr) { + return {}; } - - if (data.size() < sizeof(Idmap_header)) { - LOG(ERROR) << "Idmap header is too small."; - return false; + const auto* data = ReadType(in_out_data_ptr, in_out_size, label, *len); + if (data == nullptr) { + return {}; } - - auto header = reinterpret_cast(data.data()); - if (dtohl(header->magic) != kIdmapMagic) { - LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)", - dtohl(header->magic), kIdmapMagic); - return false; + // Strings are padded to the next 4 byte boundary. + const uint32_t padding_size = (4U - ((size_t)*in_out_data_ptr & 0x3U)) % 4U; + for (uint32_t i = 0; i < padding_size; i++) { + if (**in_out_data_ptr != 0) { + LOG(ERROR) << " Idmap padding of " << label << " is non-zero."; + return {}; + } + *in_out_data_ptr += sizeof(uint8_t); + *in_out_size -= sizeof(uint8_t); } - - if (dtohl(header->version) != kIdmapCurrentVersion) { - // We are strict about versions because files with this format are auto-generated and don't need - // backwards compatibility. - LOG(ERROR) << StringPrintf("Version mismatch in Idmap (was 0x%08x, expected 0x%08x)", - dtohl(header->version), kIdmapCurrentVersion); - return false; - } - - return true; + return std::string_view(data, *len); +} } LoadedIdmap::LoadedIdmap(std::string&& idmap_path, - const time_t last_mod_time, const Idmap_header* header, const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, const Idmap_target_entry_inline* target_inline_entries, const Idmap_overlay_entry* overlay_entries, - ResStringPool* string_pool) + std::unique_ptr&& string_pool, + std::string_view overlay_apk_path, + std::string_view target_apk_path) : header_(header), data_header_(data_header), target_entries_(target_entries), target_inline_entries_(target_inline_entries), overlay_entries_(overlay_entries), - string_pool_(string_pool), + string_pool_(std::move(string_pool)), idmap_path_(std::move(idmap_path)), - idmap_last_mod_time_(last_mod_time) { - - size_t length = strnlen(reinterpret_cast(header_->overlay_path), - arraysize(header_->overlay_path)); - overlay_apk_path_.assign(reinterpret_cast(header_->overlay_path), length); - - length = strnlen(reinterpret_cast(header_->target_path), - arraysize(header_->target_path)); - target_apk_path_.assign(reinterpret_cast(header_->target_path), length); -} + overlay_apk_path_(overlay_apk_path), + target_apk_path_(target_apk_path), + idmap_last_mod_time_(getFileModDate(idmap_path_.data())) {} std::unique_ptr LoadedIdmap::Load(const StringPiece& idmap_path, const StringPiece& idmap_data) { ATRACE_CALL(); - if (!IsValidIdmapHeader(idmap_data)) { + size_t data_size = idmap_data.size(); + auto data_ptr = reinterpret_cast(idmap_data.data()); + + // Parse the idmap header + auto header = ReadType(&data_ptr, &data_size, "header"); + if (header == nullptr) { + return {}; + } + if (dtohl(header->magic) != kIdmapMagic) { + LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)", + dtohl(header->magic), kIdmapMagic); + return {}; + } + if (dtohl(header->version) != kIdmapCurrentVersion) { + // We are strict about versions because files with this format are generated at runtime and + // don't need backwards compatibility. + LOG(ERROR) << StringPrintf("Version mismatch in Idmap (was 0x%08x, expected 0x%08x)", + dtohl(header->version), kIdmapCurrentVersion); + return {}; + } + std::optional overlay_path = ReadString(&data_ptr, &data_size, "overlay path"); + if (!overlay_path) { + return {}; + } + std::optional target_path = ReadString(&data_ptr, &data_size, "target path"); + if (!target_path) { + return {}; + } + if (!ReadString(&data_ptr, &data_size, "debug info")) { return {}; } - auto header = reinterpret_cast(idmap_data.data()); - const uint8_t* data_ptr = reinterpret_cast(idmap_data.data()) + header->Size(); - size_t data_size = idmap_data.size() - header->Size(); - - // Currently idmap2 can only generate one data block. - auto data_header = reinterpret_cast(data_ptr); - data_ptr += sizeof(*data_header); - data_size -= sizeof(*data_header); - - // Make sure there is enough space for the target entries declared in the header - const auto target_entries = reinterpret_cast(data_ptr); - if (data_size / sizeof(Idmap_target_entry) < - static_cast(dtohl(data_header->target_entry_count))) { - LOG(ERROR) << StringPrintf("Idmap too small for the number of target entries (%d)", - (int)dtohl(data_header->target_entry_count)); + // Parse the idmap data blocks. Currently idmap2 can only generate one data block. + auto data_header = ReadType(&data_ptr, &data_size, "data header"); + if (data_header == nullptr) { return {}; } - - // Advance the data pointer past the target entries. - const size_t target_entry_size_bytes = - (dtohl(data_header->target_entry_count) * sizeof(Idmap_target_entry)); - data_ptr += target_entry_size_bytes; - data_size -= target_entry_size_bytes; - - // Make sure there is enough space for the target entries declared in the header. - const auto target_inline_entries = reinterpret_cast(data_ptr); - if (data_size / sizeof(Idmap_target_entry_inline) < - static_cast(dtohl(data_header->target_inline_entry_count))) { - LOG(ERROR) << StringPrintf("Idmap too small for the number of target inline entries (%d)", - (int)dtohl(data_header->target_inline_entry_count)); + auto target_entries = ReadType(&data_ptr, &data_size, "target", + dtohl(data_header->target_entry_count)); + if (target_entries == nullptr) { return {}; } - - // Advance the data pointer past the target entries. - const size_t target_inline_entry_size_bytes = - (dtohl(data_header->target_inline_entry_count) * sizeof(Idmap_target_entry_inline)); - data_ptr += target_inline_entry_size_bytes; - data_size -= target_inline_entry_size_bytes; - - // Make sure there is enough space for the overlay entries declared in the header. - const auto overlay_entries = reinterpret_cast(data_ptr); - if (data_size / sizeof(Idmap_overlay_entry) < - static_cast(dtohl(data_header->overlay_entry_count))) { - LOG(ERROR) << StringPrintf("Idmap too small for the number of overlay entries (%d)", - (int)dtohl(data_header->overlay_entry_count)); + auto target_inline_entries = ReadType( + &data_ptr, &data_size, "target inline", dtohl(data_header->target_inline_entry_count)); + if (target_inline_entries == nullptr) { return {}; } - - // Advance the data pointer past the overlay entries. - const size_t overlay_entry_size_bytes = - (dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry)); - data_ptr += overlay_entry_size_bytes; - data_size -= overlay_entry_size_bytes; - - // Read the idmap string pool that holds the value of inline string entries. - uint32_t string_pool_size = dtohl(*reinterpret_cast(data_ptr)); - data_ptr += sizeof(uint32_t); - data_size -= sizeof(uint32_t); - - if (data_size < string_pool_size) { - LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)", - (int)string_pool_size); + auto overlay_entries = ReadType(&data_ptr, &data_size, "target inline", + dtohl(data_header->overlay_entry_count)); + if (overlay_entries == nullptr) { + return {}; + } + std::optional string_pool = ReadString(&data_ptr, &data_size, "string pool"); + if (!string_pool) { return {}; } - auto idmap_string_pool = util::make_unique(); - if (string_pool_size > 0) { - status_t err = idmap_string_pool->setTo(data_ptr, string_pool_size); + if (!string_pool->empty()) { + const status_t err = idmap_string_pool->setTo(string_pool->data(), string_pool->size()); if (err != NO_ERROR) { LOG(ERROR) << "idmap string pool corrupt."; return {}; @@ -296,12 +326,10 @@ std::unique_ptr LoadedIdmap::Load(const StringPiece& idmap_pa } // Can't use make_unique because LoadedIdmap constructor is private. - auto loaded_idmap = std::unique_ptr( - new LoadedIdmap(idmap_path.to_string(), getFileModDate(idmap_path.data()), header, - data_header, target_entries, target_inline_entries, overlay_entries, - idmap_string_pool.release())); - - return std::move(loaded_idmap); + return std::unique_ptr( + new LoadedIdmap(idmap_path.to_string(), header, data_header, target_entries, + target_inline_entries, overlay_entries, std::move(idmap_string_pool), + *target_path, *overlay_path)); } bool LoadedIdmap::IsUpToDate() const { diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h index fdab03ba2de44..fd9a8d13e0c68 100644 --- a/libs/androidfw/include/androidfw/Idmap.h +++ b/libs/androidfw/include/androidfw/Idmap.h @@ -31,6 +31,11 @@ namespace android { class LoadedIdmap; class IdmapResMap; +struct Idmap_header; +struct Idmap_data_header; +struct Idmap_target_entry; +struct Idmap_target_entry_inline; +struct Idmap_overlay_entry; // A string pool for overlay apk assets. The string pool holds the strings of the overlay resources // table and additionally allows for loading strings from the idmap string pool. The idmap string @@ -148,29 +153,29 @@ class LoadedIdmap { const StringPiece& idmap_data); // Returns the path to the IDMAP. - inline const std::string& IdmapPath() const { + std::string_view IdmapPath() const { return idmap_path_; } // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated. - inline const std::string& OverlayApkPath() const { + std::string_view OverlayApkPath() const { return overlay_apk_path_; } // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated. - inline const std::string& TargetApkPath() const { + std::string_view TargetApkPath() const { return target_apk_path_; } // Returns a mapping from target resource ids to overlay values. - inline const IdmapResMap GetTargetResourcesMap( + const IdmapResMap GetTargetResourcesMap( uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const { return IdmapResMap(data_header_, target_entries_, target_inline_entries_, target_assigned_package_id, overlay_ref_table); } // Returns a dynamic reference table for a loaded overlay package. - inline const OverlayDynamicRefTable GetOverlayDynamicRefTable( + const OverlayDynamicRefTable GetOverlayDynamicRefTable( uint8_t target_assigned_package_id) const { return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id); } @@ -190,22 +195,23 @@ class LoadedIdmap { const Idmap_overlay_entry* overlay_entries_; const std::unique_ptr string_pool_; - const std::string idmap_path_; - std::string overlay_apk_path_; - std::string target_apk_path_; - const time_t idmap_last_mod_time_; + std::string idmap_path_; + std::string_view overlay_apk_path_; + std::string_view target_apk_path_; + time_t idmap_last_mod_time_; private: DISALLOW_COPY_AND_ASSIGN(LoadedIdmap); explicit LoadedIdmap(std::string&& idmap_path, - time_t last_mod_time, const Idmap_header* header, const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, const Idmap_target_entry_inline* target_inline_entries, const Idmap_overlay_entry* overlay_entries, - ResStringPool* string_pool); + std::unique_ptr&& string_pool, + std::string_view overlay_apk_path, + std::string_view target_apk_path); friend OverlayStringPool; }; diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index fb5f864731891..d1622a03a318c 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -44,7 +44,7 @@ namespace android { constexpr const static uint32_t kIdmapMagic = 0x504D4449u; -constexpr const static uint32_t kIdmapCurrentVersion = 0x00000005u; +constexpr const static uint32_t kIdmapCurrentVersion = 0x00000006u; /** * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of @@ -1700,56 +1700,6 @@ inline ResTable_overlayable_policy_header::PolicyFlags& operator |=( return first; } -struct Idmap_header { - // Always 0x504D4449 ('IDMP') - uint32_t magic; - - uint32_t version; - - uint32_t target_crc32; - uint32_t overlay_crc32; - - uint32_t fulfilled_policies; - uint32_t enforce_overlayable; - - uint8_t target_path[256]; - uint8_t overlay_path[256]; - - uint32_t debug_info_size; - uint8_t debug_info[0]; - - size_t Size() const; -}; - -struct Idmap_data_header { - uint8_t target_package_id; - uint8_t overlay_package_id; - - // Padding to ensure 4 byte alignment for target_entry_count - uint16_t p0; - - uint32_t target_entry_count; - uint32_t target_inline_entry_count; - uint32_t overlay_entry_count; - - uint32_t string_pool_index_offset; -}; - -struct Idmap_target_entry { - uint32_t target_id; - uint32_t overlay_id; -}; - -struct Idmap_target_entry_inline { - uint32_t target_id; - Res_value value; -}; - -struct Idmap_overlay_entry { - uint32_t overlay_id; - uint32_t target_id; -}; - class AssetManager2; /** diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h index aceeeccccb611..c59b5b6c51a2d 100644 --- a/libs/androidfw/include/androidfw/Util.h +++ b/libs/androidfw/include/androidfw/Util.h @@ -128,10 +128,14 @@ std::string Utf16ToUtf8(const StringPiece16& utf16); std::vector SplitAndLowercase(const android::StringPiece& str, char sep); template -bool IsFourByteAligned(const incfs::map_ptr& data) { +inline bool IsFourByteAligned(const incfs::map_ptr& data) { return ((size_t)data.unsafe_ptr() & 0x3U) == 0; } +inline bool IsFourByteAligned(const void* data) { + return ((size_t)data & 0x3U) == 0; +} + } // namespace util } // namespace android diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap index 3ab244eb084ab..6f0104a52f68f 100644 Binary files a/libs/androidfw/tests/data/overlay/overlay.idmap and b/libs/androidfw/tests/data/overlay/overlay.idmap differ