Merge "Don't verify runtime only opcodes in the data-flow phase of verification."
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f551d69..1d04151 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2135,15 +2135,12 @@
     case Instruction::INVOKE_VIRTUAL_RANGE:
     case Instruction::INVOKE_SUPER:
     case Instruction::INVOKE_SUPER_RANGE: {
-      if (inst->VRegA() == 0) {
-        Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invoke_virtual/super needs at least receiver";
-      }
       bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE ||
                        inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
       bool is_super = (inst->Opcode() == Instruction::INVOKE_SUPER ||
                        inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
-      mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL,
-                                                                   is_range, is_super);
+      mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL, is_range,
+                                                              is_super);
       const RegType* return_type = nullptr;
       if (called_method != nullptr) {
         Thread* self = Thread::Current();
@@ -3016,6 +3013,26 @@
   // Resolve the method. This could be an abstract or concrete method depending on what sort of call
   // we're making.
   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+
+  // As the method may not have been resolved, make this static check against what we expect.
+  const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
+  uint32_t shorty_idx = dex_file_->GetProtoId(method_id.proto_idx_).shorty_idx_;
+  uint32_t shorty_len;
+  const char* descriptor = dex_file_->StringDataAndUtf16LengthByIdx(shorty_idx, &shorty_len);
+  int32_t sig_registers = method_type == METHOD_STATIC ? 0 : 1;
+  for (size_t i = 1; i < shorty_len; i++) {
+    if (descriptor[i] == 'J' || descriptor[i] == 'D') {
+      sig_registers += 2;
+    } else {
+      sig_registers++;
+    }
+  }
+  if (inst->VRegA() != sig_registers) {
+    Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation, expected " << inst->VRegA() <<
+        " arguments, found " << sig_registers;
+    return nullptr;
+  }
+
   mirror::ArtMethod* res_method = ResolveMethodAndCheckAccess(method_idx, method_type);
   if (res_method == NULL) {  // error or class is unresolved
     return NULL;