Add patchoat check that input oat file has patch section.

Do this check before opening the output file in case this could be
causing the file to become truncated.

Bug: 27723864

(cherry-picked from commit 99503b9805def2ed7d4fe4bf285c6fdd8ddce6ed)

Change-Id: I2134ec65fb6d9582f4eb4c2619a5ffb7b987eaa6
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 1d80bda..7a3071e 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -1100,6 +1100,7 @@
     if (input_oat == nullptr) {
       // Unlikely, but ensure exhaustive logging in non-0 exit code case
       LOG(ERROR) << "Failed to open input oat file by its FD" << input_oat_fd;
+      return EXIT_FAILURE;
     }
   } else {
     CHECK(!input_oat_filename.empty());
@@ -1108,9 +1109,21 @@
       int err = errno;
       LOG(ERROR) << "Failed to open input oat file " << input_oat_filename
           << ": " << strerror(err) << "(" << err << ")";
+      return EXIT_FAILURE;
     }
   }
 
+  std::string error_msg;
+  std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat.get(), PROT_READ, MAP_PRIVATE, &error_msg));
+  if (elf.get() == nullptr) {
+    LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
+    return EXIT_FAILURE;
+  }
+  if (!elf->HasSection(".text.oat_patches")) {
+    LOG(ERROR) << "missing oat patch section in input oat file " << input_oat->GetPath();
+    return EXIT_FAILURE;
+  }
+
   if (output_oat_fd != -1) {
     if (output_oat_filename.empty()) {
       output_oat_filename = "output-oat-file";
@@ -1144,23 +1157,15 @@
     }
   };
 
-  if (input_oat.get() == nullptr || output_oat.get() == nullptr) {
-    LOG(ERROR) << "Failed to open input/output oat files";
+  if (output_oat.get() == nullptr) {
     cleanup(false);
     return EXIT_FAILURE;
   }
 
   if (match_delta) {
-    std::string error_msg;
     // Figure out what the current delta is so we can match it to the desired delta.
-    std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat.get(), PROT_READ, MAP_PRIVATE,
-                                               &error_msg));
     off_t current_delta = 0;
-    if (elf.get() == nullptr) {
-      LOG(ERROR) << "unable to open oat file " << input_oat->GetPath() << " : " << error_msg;
-      cleanup(false);
-      return EXIT_FAILURE;
-    } else if (!ReadOatPatchDelta(elf.get(), &current_delta, &error_msg)) {
+    if (!ReadOatPatchDelta(elf.get(), &current_delta, &error_msg)) {
       LOG(ERROR) << "Unable to get current delta: " << error_msg;
       cleanup(false);
       return EXIT_FAILURE;
@@ -1183,7 +1188,6 @@
 
   ScopedFlock output_oat_lock;
   if (lock_output) {
-    std::string error_msg;
     if (!output_oat_lock.Init(output_oat.get(), &error_msg)) {
       LOG(ERROR) << "Unable to lock output oat " << output_oat->GetPath() << ": " << error_msg;
       cleanup(false);
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 3b4b88d..096f003 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1830,6 +1830,14 @@
   }
 }
 
+bool ElfFile::HasSection(const std::string& name) const {
+  if (elf64_.get() != nullptr) {
+    return elf64_->FindSectionByName(name) != nullptr;
+  } else {
+    return elf32_->FindSectionByName(name) != nullptr;
+  }
+}
+
 uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
                                     const std::string& symbol_name,
                                     bool build_map) {
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index b5229b5..c3616f7 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -69,6 +69,8 @@
 
   bool GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size) const;
 
+  bool HasSection(const std::string& name) const;
+
   uint64_t FindSymbolAddress(unsigned section_type,
                              const std::string& symbol_name,
                              bool build_map);