ART: Check long and double register pairs in invokes

For invokes, ensure that long and double parameters are actually
in registers pairs. We were testing the pair, but skipping the
actual high parameter register.

Bug: 17410612
Change-Id: I8f4c3335ea8b7dc3cf252bee52a5a706ae8905f8
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 4d88227..b86a7ee 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3372,11 +3372,27 @@
             << " but expected " << reg_type;
         return nullptr;
       }
-    } else if (!work_line_->VerifyRegisterType(this, get_reg, reg_type)) {
-      // Continue on soft failures. We need to find possible hard failures to avoid problems in the
-      // compiler.
-      if (have_pending_hard_failure_) {
-        return nullptr;
+    } else {
+      if (!work_line_->VerifyRegisterType(this, get_reg, reg_type)) {
+        // Continue on soft failures. We need to find possible hard failures to avoid problems in
+        // the compiler.
+        if (have_pending_hard_failure_) {
+          return nullptr;
+        }
+      } else if (reg_type.IsLongOrDoubleTypes()) {
+        // Check that registers are consecutive (for non-range invokes). Invokes are the only
+        // instructions not specifying register pairs by the first component, but require them
+        // nonetheless. Only check when there's an actual register in the parameters. If there's
+        // none, this will fail below.
+        if (!is_range && sig_registers + 1 < expected_args) {
+          uint32_t second_reg = arg[sig_registers + 1];
+          if (second_reg != get_reg + 1) {
+            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation, long or double parameter "
+                "at index " << sig_registers << " is not a pair: " << get_reg << " + "
+                << second_reg << ".";
+            return nullptr;
+          }
+        }
       }
     }
     sig_registers += reg_type.IsLongOrDoubleTypes() ?  2 : 1;