Make dex file verifier check for dups between direct and virtual methods.

The dex file verifier now rejects classes that have the same method index
in both direct and virtual methods.

Bug: 17878919
Change-Id: I431b4715e39ca2cce4df3ebef020b7ec0661a4c0
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index a66c38e..5fa58f7 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -465,7 +465,9 @@
 }
 
 bool DexFileVerifier::CheckClassDataItemMethod(uint32_t idx, uint32_t access_flags,
-                                               uint32_t code_offset, bool expect_direct) {
+                                               uint32_t code_offset,
+                                               std::unordered_set<uint32_t>& direct_method_indexes,
+                                               bool expect_direct) {
   if (!CheckIndex(idx, header_->method_ids_size_, "class_data_item method_idx")) {
     return false;
   }
@@ -480,6 +482,13 @@
     return false;
   }
 
+  if (expect_direct) {
+    direct_method_indexes.insert(idx);
+  } else if (direct_method_indexes.find(idx) != direct_method_indexes.end()) {
+    ErrorStringPrintf("Found virtual method with same index as direct method: %d", idx);
+    return false;
+  }
+
   constexpr uint32_t access_method_mask = kAccJavaFlagsMask | kAccConstructor |
       kAccDeclaredSynchronized;
   if (UNLIKELY(((access_flags & ~access_method_mask) != 0) ||
@@ -682,6 +691,7 @@
 
 bool DexFileVerifier::CheckIntraClassDataItem() {
   ClassDataItemIterator it(*dex_file_, ptr_);
+  std::unordered_set<uint32_t> direct_method_indexes;
 
   // These calls use the raw access flags to check whether the whole dex field is valid.
 
@@ -697,13 +707,13 @@
   }
   for (; it.HasNextDirectMethod(); it.Next()) {
     if (!CheckClassDataItemMethod(it.GetMemberIndex(), it.GetRawMemberAccessFlags(),
-        it.GetMethodCodeItemOffset(), true)) {
+        it.GetMethodCodeItemOffset(), direct_method_indexes, true)) {
       return false;
     }
   }
   for (; it.HasNextVirtualMethod(); it.Next()) {
     if (!CheckClassDataItemMethod(it.GetMemberIndex(), it.GetRawMemberAccessFlags(),
-        it.GetMethodCodeItemOffset(), false)) {
+        it.GetMethodCodeItemOffset(), direct_method_indexes, false)) {
       return false;
     }
   }