diff options
author | 2017-03-02 16:36:31 -0800 | |
---|---|---|
committer | 2017-03-02 19:51:11 -0800 | |
commit | 41b2f537aca2c9779e39651fb222a1132a7eff56 (patch) | |
tree | 8a916e481bf5a66dd0b14d84509d5d97c3de6f2b | |
parent | f040eca7329382d48dc2b8bfc228ee3f27c9f13d (diff) |
Add nullptr and size check for opening a mem mapped dex file.
The bug has an apk with 0 size classes.dex. When dex2oat tries to open
the file for layout, it crashes. This adds checks to ensure that the mem
map isn't null and has a sane size before opening it as a dex file.
Bug: 35892406
Test: mm test-art-host
Change-Id: I5f6b5a1e7bbccf4fe3483b68023d51436eb71805
-rw-r--r-- | compiler/oat_test.cc | 23 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 4 | ||||
-rw-r--r-- | runtime/dex_file.cc | 8 |
3 files changed, 35 insertions, 0 deletions
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index 66111f6e23..e2233e4bbd 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -265,6 +265,7 @@ class OatTest : public CommonCompilerTest { void TestDexFileInput(bool verify, bool low_4gb, bool use_profile); void TestZipFileInput(bool verify); + void TestZipFileInputWithEmptyDex(); std::unique_ptr<const InstructionSetFeatures> insn_features_; std::unique_ptr<QuickCompilerCallbacks> callbacks_; @@ -821,6 +822,28 @@ TEST_F(OatTest, ZipFileInputCheckVerifier) { TestZipFileInput(true); } +void OatTest::TestZipFileInputWithEmptyDex() { + ScratchFile zip_file; + ZipBuilder zip_builder(zip_file.GetFile()); + bool success = zip_builder.AddFile("classes.dex", nullptr, 0); + ASSERT_TRUE(success); + success = zip_builder.Finish(); + ASSERT_TRUE(success) << strerror(errno); + + SafeMap<std::string, std::string> key_value_store; + key_value_store.Put(OatHeader::kImageLocationKey, "test.art"); + std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() }; // NOLINT [readability/braces] [4] + ScratchFile oat_file, vdex_file(oat_file, ".vdex"); + std::unique_ptr<ProfileCompilationInfo> profile_compilation_info(new ProfileCompilationInfo()); + success = WriteElf(vdex_file.GetFile(), oat_file.GetFile(), input_filenames, + key_value_store, /*verify*/false, profile_compilation_info.get()); + ASSERT_FALSE(success); +} + +TEST_F(OatTest, ZipFileInputWithEmptyDex) { + TestZipFileInputWithEmptyDex(); +} + TEST_F(OatTest, UpdateChecksum) { InstructionSet insn_set = kX86; std::string error_msg; diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 34d2ec9cde..08608a602d 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -2260,6 +2260,10 @@ bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_fil ZipEntry* zip_entry = oat_dex_file->source_.GetZipEntry(); std::unique_ptr<MemMap> mem_map( zip_entry->ExtractToMemMap(location.c_str(), "classes.dex", &error_msg)); + if (mem_map == nullptr) { + LOG(ERROR) << "Failed to extract dex file to mem map for layout: " << error_msg; + return false; + } dex_file = DexFile::Open(location, zip_entry->GetCrc32(), std::move(mem_map), diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index b6a2e09719..35e9d5db29 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -179,6 +179,14 @@ std::unique_ptr<const DexFile> DexFile::Open(const std::string& location, std::string* error_msg) { ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location); CHECK(map.get() != nullptr); + + if (map->Size() < sizeof(DexFile::Header)) { + *error_msg = StringPrintf( + "DexFile: failed to open dex file '%s' that is too short to have a header", + location.c_str()); + return nullptr; + } + std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), map->Size(), location, |