Fix image checksum verification.
Move over the separator ':' for checking subsequent dex file
checksums. The bug, introduced in
https://android-review.googlesource.com/1091189 ,
caused rejection of oat files if the boot class path had
more than one module that was not part of the boot image.
Test: Add a new test to image_space_test.
Test: Manual fake OTA with extra logging for checksum mismatch.
Bug: 119800099
Bug: 144146443
Change-Id: I9eb8328348b30ee4769468924f9e6ac65b70d4cb
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 9ff799c..57584ed 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -3378,6 +3378,7 @@
std::string(oat_checksums).c_str());
return false;
}
+ oat_checksums.remove_prefix(1u);
}
}
if (!oat_checksums.empty()) {
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index 34df447..f3398e9 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -17,8 +17,10 @@
#include <gtest/gtest.h>
#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
#include "base/stl_util.h"
+#include "class_linker.h"
#include "dexopt_test.h"
#include "noop_compiler_callbacks.h"
@@ -110,6 +112,56 @@
EXPECT_FALSE(ImageSpace::ValidateOatFile(*oat, &error_msg));
}
+TEST_F(DexoptTest, Checksums) {
+ Runtime* runtime = Runtime::Current();
+ ASSERT_TRUE(runtime != nullptr);
+ ASSERT_FALSE(runtime->GetHeap()->GetBootImageSpaces().empty());
+
+ std::vector<std::string> bcp = runtime->GetBootClassPath();
+ std::vector<std::string> bcp_locations = runtime->GetBootClassPathLocations();
+ std::vector<const DexFile*> dex_files = runtime->GetClassLinker()->GetBootClassPath();
+
+ std::string error_msg;
+ auto create_and_verify = [&]() {
+ std::string checksums = gc::space::ImageSpace::GetBootClassPathChecksums(
+ ArrayRef<gc::space::ImageSpace* const>(runtime->GetHeap()->GetBootImageSpaces()),
+ ArrayRef<const DexFile* const>(dex_files));
+ return gc::space::ImageSpace::VerifyBootClassPathChecksums(
+ checksums,
+ android::base::Join(bcp_locations, ':'),
+ runtime->GetImageLocation(),
+ ArrayRef<const std::string>(bcp_locations),
+ ArrayRef<const std::string>(bcp),
+ kRuntimeISA,
+ gc::space::ImageSpaceLoadingOrder::kSystemFirst,
+ &error_msg);
+ };
+
+ ASSERT_TRUE(create_and_verify()) << error_msg;
+
+ std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
+ for (const std::string& src : { GetDexSrc1(), GetDexSrc2() }) {
+ std::vector<std::unique_ptr<const DexFile>> new_dex_files;
+ const ArtDexFileLoader dex_file_loader;
+ ASSERT_TRUE(dex_file_loader.Open(src.c_str(),
+ src,
+ /*verify=*/ true,
+ /*verify_checksum=*/ false,
+ &error_msg,
+ &new_dex_files))
+ << error_msg;
+
+ bcp.push_back(src);
+ bcp_locations.push_back(src);
+ for (std::unique_ptr<const DexFile>& df : new_dex_files) {
+ dex_files.push_back(df.get());
+ opened_dex_files.push_back(std::move(df));
+ }
+
+ ASSERT_TRUE(create_and_verify()) << error_msg;
+ }
+}
+
template <bool kImage, bool kRelocate, bool kImageDex2oat>
class ImageSpaceLoadingTest : public CommonRuntimeTest {
protected: