Fix CTS crash from DexFile refactoring
Avoid path to nullptr access introduced by the previous refactoring.
Bug: 22322814
Change-Id: Id8874b26c072a11b0494e8126f8b0602a7c5b9e8
Test: m test-art-host, cts-tradefed run cts --skip-preconditions --skip-device-info --module vm-tests-tf
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 409fbba..0af086c 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -323,7 +323,7 @@
ScopedTrace trace("Dex file open from Zip Archive " + std::string(location));
CHECK(!location.empty());
std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg));
- if (zip_entry.get() == nullptr) {
+ if (zip_entry == nullptr) {
*error_code = ZipOpenErrorCode::kEntryNotFound;
return nullptr;
}
@@ -333,7 +333,7 @@
return nullptr;
}
std::unique_ptr<MemMap> map(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg));
- if (map.get() == nullptr) {
+ if (map == nullptr) {
*error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(),
error_msg->c_str());
*error_code = ZipOpenErrorCode::kExtractToMemoryError;
@@ -349,9 +349,15 @@
verify_checksum,
error_msg,
&verify_result);
- if (dex_file != nullptr) {
- dex_file->mem_map_.reset(map.release());
+ if (dex_file == nullptr) {
+ if (verify_result == VerifyResult::kVerifyNotAttempted) {
+ *error_code = ZipOpenErrorCode::kDexFileError;
+ } else {
+ *error_code = ZipOpenErrorCode::kVerifyError;
+ }
+ return nullptr;
}
+ dex_file->mem_map_.reset(map.release());
if (!dex_file->DisableWrite()) {
*error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str());
*error_code = ZipOpenErrorCode::kMakeReadOnlyError;
@@ -440,6 +446,9 @@
bool verify_checksum,
std::string* error_msg,
VerifyResult* verify_result) {
+ if (verify_result != nullptr) {
+ *verify_result = VerifyResult::kVerifyNotAttempted;
+ }
std::unique_ptr<DexFile> dex_file(new DexFile(base,
size,
location,
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 28aeb1e..29b8c3a 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -1049,6 +1049,7 @@
ZipOpenErrorCode* error_code);
enum class VerifyResult { // private
+ kVerifyNotAttempted,
kVerifySucceeded,
kVerifyFailed
};
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index 3dffc40..8dd5f37 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -112,6 +112,55 @@
"AGNsYXNzZXMuZGV4VVQFAANkDaFXdXgLAAEE5AMBAASIEwAAUEsFBgAAAAABAAEAUQAAAEUAAAAA"
"AA==";
+static const char kRawZipClassesDexPresent[] =
+ "UEsDBBQAAAAIANVRN0ms99lIMQEAACACAAALABwAY2xhc3Nlcy5kZXhVVAkAAwFj5VcUY+VXdXgL"
+ "AAEE5AMBAASIEwAAS0mt4DIwtmDYYdV9csrcks83lpxZN2vD8f/1p1beWX3vabQCEwNDAQMDQ0WY"
+ "iRADFPQwMjBwMEDEWYB4AhADlTEsYEAAZiDeAcRApQwXgNgAyPgApJWAtBYQGwGxGxAHAnEIEEcA"
+ "cS4jRD0T1Fw2KM0ENZMVypZhRLIIqIMdag9CBMFnhtJ1jDA5RrBcMSPE7AIBkIl8UFGgP6Fu4IOa"
+ "wczAZpOZl1lix8Dm45uYmWfNIOSTlViWqJ+TmJeu75+UlZpcYs3ACZLSA4kzMIYxMIX5MAhHIykL"
+ "LinKzEu3ZmDJBSoDOZiPgRlMgv3T2MDygZGRs4OJB8n9MBoWzrAwmQD1Eyy8WZHCmg0pvBkVIGpA"
+ "Yc4oABEHhRuTAsRMUDwwQ9WAwoJBAaIGHE5Q9aB4BgBQSwECHgMUAAAACADVUTdJrPfZSDEBAAAg"
+ "AgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAAwFj5Vd1eAsAAQTkAwEABIgTAABQ"
+ "SwUGAAAAAAEAAQBRAAAAdgEAAAAA";
+
+static const char kRawZipClassesDexAbsent[] =
+ "UEsDBBQAAAAIANVRN0ms99lIMQEAACACAAAOABwAbm90Y2xhc3Nlcy5kZXhVVAkAAwFj5VcUY+VX"
+ "dXgLAAEE5AMBAASIEwAAS0mt4DIwtmDYYdV9csrcks83lpxZN2vD8f/1p1beWX3vabQCEwNDAQMD"
+ "Q0WYiRADFPQwMjBwMEDEWYB4AhADlTEsYEAAZiDeAcRApQwXgNgAyPgApJWAtBYQGwGxGxAHAnEI"
+ "EEcAcS4jRD0T1Fw2KM0ENZMVypZhRLIIqIMdag9CBMFnhtJ1jDA5RrBcMSPE7AIBkIl8UFGgP6Fu"
+ "4IOawczAZpOZl1lix8Dm45uYmWfNIOSTlViWqJ+TmJeu75+UlZpcYs3ACZLSA4kzMIYxMIX5MAhH"
+ "IykLLinKzEu3ZmDJBSoDOZiPgRlMgv3T2MDygZGRs4OJB8n9MBoWzrAwmQD1Eyy8WZHCmg0pvBkV"
+ "IGpAYc4oABEHhRuTAsRMUDwwQ9WAwoJBAaIGHE5Q9aB4BgBQSwECHgMUAAAACADVUTdJrPfZSDEB"
+ "AAAgAgAADgAYAAAAAAAAAAAAoIEAAAAAbm90Y2xhc3Nlcy5kZXhVVAUAAwFj5Vd1eAsAAQTkAwEA"
+ "BIgTAABQSwUGAAAAAAEAAQBUAAAAeQEAAAAA";
+
+static const char kRawZipThreeDexFiles[] =
+ "UEsDBBQAAAAIAP1WN0ms99lIMQEAACACAAAMABwAY2xhc3NlczIuZGV4VVQJAAOtbOVXrWzlV3V4"
+ "CwABBOQDAQAEiBMAAEtJreAyMLZg2GHVfXLK3JLPN5acWTdrw/H/9adW3ll972m0AhMDQwEDA0NF"
+ "mIkQAxT0MDIwcDBAxFmAeAIQA5UxLGBAAGYg3gHEQKUMF4DYAMj4AKSVgLQWEBsBsRsQBwJxCBBH"
+ "AHEuI0Q9E9RcNijNBDWTFcqWYUSyCKiDHWoPQgTBZ4bSdYwwOUawXDEjxOwCAZCJfFBRoD+hbuCD"
+ "msHMwGaTmZdZYsfA5uObmJlnzSDkk5VYlqifk5iXru+flJWaXGLNwAmS0gOJMzCGMTCF+TAIRyMp"
+ "Cy4pysxLt2ZgyQUqAzmYj4EZTIL909jA8oGRkbODiQfJ/TAaFs6wMJkA9RMsvFmRwpoNKbwZFSBq"
+ "QGHOKAARB4UbkwLETFA8MEPVgMKCQQGiBhxOUPWgeAYAUEsDBBQAAAAIAABXN0ms99lIMQEAACAC"
+ "AAAMABwAY2xhc3NlczMuZGV4VVQJAAOvbOVXr2zlV3V4CwABBOQDAQAEiBMAAEtJreAyMLZg2GHV"
+ "fXLK3JLPN5acWTdrw/H/9adW3ll972m0AhMDQwEDA0NFmIkQAxT0MDIwcDBAxFmAeAIQA5UxLGBA"
+ "AGYg3gHEQKUMF4DYAMj4AKSVgLQWEBsBsRsQBwJxCBBHAHEuI0Q9E9RcNijNBDWTFcqWYUSyCKiD"
+ "HWoPQgTBZ4bSdYwwOUawXDEjxOwCAZCJfFBRoD+hbuCDmsHMwGaTmZdZYsfA5uObmJlnzSDkk5VY"
+ "lqifk5iXru+flJWaXGLNwAmS0gOJMzCGMTCF+TAIRyMpCy4pysxLt2ZgyQUqAzmYj4EZTIL909jA"
+ "8oGRkbODiQfJ/TAaFs6wMJkA9RMsvFmRwpoNKbwZFSBqQGHOKAARB4UbkwLETFA8MEPVgMKCQQGi"
+ "BhxOUPWgeAYAUEsDBBQAAAAIANVRN0ms99lIMQEAACACAAALABwAY2xhc3Nlcy5kZXhVVAkAAwFj"
+ "5VetbOVXdXgLAAEE5AMBAASIEwAAS0mt4DIwtmDYYdV9csrcks83lpxZN2vD8f/1p1beWX3vabQC"
+ "EwNDAQMDQ0WYiRADFPQwMjBwMEDEWYB4AhADlTEsYEAAZiDeAcRApQwXgNgAyPgApJWAtBYQGwGx"
+ "GxAHAnEIEEcAcS4jRD0T1Fw2KM0ENZMVypZhRLIIqIMdag9CBMFnhtJ1jDA5RrBcMSPE7AIBkIl8"
+ "UFGgP6Fu4IOawczAZpOZl1lix8Dm45uYmWfNIOSTlViWqJ+TmJeu75+UlZpcYs3ACZLSA4kzMIYx"
+ "MIX5MAhHIykLLinKzEu3ZmDJBSoDOZiPgRlMgv3T2MDygZGRs4OJB8n9MBoWzrAwmQD1Eyy8WZHC"
+ "mg0pvBkVIGpAYc4oABEHhRuTAsRMUDwwQ9WAwoJBAaIGHE5Q9aB4BgBQSwECHgMUAAAACAD9VjdJ"
+ "rPfZSDEBAAAgAgAADAAYAAAAAAAAAAAAoIEAAAAAY2xhc3NlczIuZGV4VVQFAAOtbOVXdXgLAAEE"
+ "5AMBAASIEwAAUEsBAh4DFAAAAAgAAFc3Saz32UgxAQAAIAIAAAwAGAAAAAAAAAAAAKCBdwEAAGNs"
+ "YXNzZXMzLmRleFVUBQADr2zlV3V4CwABBOQDAQAEiBMAAFBLAQIeAxQAAAAIANVRN0ms99lIMQEA"
+ "ACACAAALABgAAAAAAAAAAACgge4CAABjbGFzc2VzLmRleFVUBQADAWPlV3V4CwABBOQDAQAEiBMA"
+ "AFBLBQYAAAAAAwADAPUAAABkBAAAAAA=";
+
static void DecodeAndWriteDexFile(const char* base64, const char* location) {
// decode base64
CHECK(base64 != nullptr);
@@ -129,22 +178,36 @@
}
}
-static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
- const char* location) {
+static bool OpenDexFilesBase64(const char* base64,
+ const char* location,
+ std::vector<std::unique_ptr<const DexFile>>* dex_files,
+ std::string* error_msg) {
DecodeAndWriteDexFile(base64, location);
- // read dex file
+ // read dex file(s)
ScopedObjectAccess soa(Thread::Current());
static constexpr bool kVerifyChecksum = true;
- std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> tmp;
- bool success = DexFile::Open(location, location, kVerifyChecksum, &error_msg, &tmp);
+ bool success = DexFile::Open(location, location, kVerifyChecksum, error_msg, &tmp);
+ if (success) {
+ for (std::unique_ptr<const DexFile>& dex_file : tmp) {
+ EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
+ EXPECT_TRUE(dex_file->IsReadOnly());
+ }
+ *dex_files = std::move(tmp);
+ }
+ return success;
+}
+
+static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
+ const char* location) {
+ // read dex files.
+ std::string error_msg;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ bool success = OpenDexFilesBase64(base64, location, &dex_files, &error_msg);
CHECK(success) << error_msg;
- EXPECT_EQ(1U, tmp.size());
- std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]);
- EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
- EXPECT_TRUE(dex_file->IsReadOnly());
- return dex_file;
+ EXPECT_EQ(1U, dex_files.size());
+ return std::move(dex_files[0]);
}
static std::unique_ptr<const DexFile> OpenDexFileInMemoryBase64(const char* base64,
@@ -456,4 +519,31 @@
EXPECT_EQ(":classes8.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes8.dex"));
}
+TEST_F(DexFileTest, ZipOpenClassesPresent) {
+ ScratchFile tmp;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ASSERT_TRUE(OpenDexFilesBase64(kRawZipClassesDexPresent, tmp.GetFilename().c_str(), &dex_files,
+ &error_msg));
+ EXPECT_EQ(dex_files.size(), 1u);
+}
+
+TEST_F(DexFileTest, ZipOpenClassesAbsent) {
+ ScratchFile tmp;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ASSERT_FALSE(OpenDexFilesBase64(kRawZipClassesDexAbsent, tmp.GetFilename().c_str(), &dex_files,
+ &error_msg));
+ EXPECT_EQ(dex_files.size(), 0u);
+}
+
+TEST_F(DexFileTest, ZipOpenThreeDexFiles) {
+ ScratchFile tmp;
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
+ ASSERT_TRUE(OpenDexFilesBase64(kRawZipThreeDexFiles, tmp.GetFilename().c_str(), &dex_files,
+ &error_msg));
+ EXPECT_EQ(dex_files.size(), 3u);
+}
+
} // namespace art