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
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 66111f6..e2233e4 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -265,6 +265,7 @@
 
   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 @@
   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 34d2ec9..08608a6 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -2260,6 +2260,10 @@
     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 b6a2e09..35e9d5d 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -179,6 +179,14 @@
                                              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,