Hard-fail get-/put-object to a non-reference field.

Bug: 21886894

(cherry picked from commit 414000ec4d728b5c85f8c6dee4f867fecde59b01)

Change-Id: Iafc32f0e45d26f3aaa2d521b98353e7cede16c6f
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index bcad9b6..89f5115 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4006,10 +4006,15 @@
       VerifyPrimitivePut(*field_type, insn_type, vregA);
     } else {
       if (!insn_type.IsAssignableFrom(*field_type)) {
-        Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
-                                                << " to be compatible with type '" << insn_type
-                                                << "' but found type '" << *field_type
-                                                << "' in put-object";
+        // If the field type is not a reference, this is a global failure rather than
+        // a class change failure as the instructions and the descriptors for the type
+        // should have been consistent within the same file at compile time.
+        VerifyError error = field_type->IsReferenceTypes() ? VERIFY_ERROR_BAD_CLASS_SOFT
+                                                           : VERIFY_ERROR_BAD_CLASS_HARD;
+        Fail(error) << "expected field " << PrettyField(field)
+                    << " to be compatible with type '" << insn_type
+                    << "' but found type '" << *field_type
+                    << "' in put-object";
         return;
       }
       work_line_->VerifyRegisterType(this, vregA, *field_type);
@@ -4033,10 +4038,15 @@
       }
     } else {
       if (!insn_type.IsAssignableFrom(*field_type)) {
-        Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
-                                          << " to be compatible with type '" << insn_type
-                                          << "' but found type '" << *field_type
-                                          << "' in get-object";
+        // If the field type is not a reference, this is a global failure rather than
+        // a class change failure as the instructions and the descriptors for the type
+        // should have been consistent within the same file at compile time.
+        VerifyError error = field_type->IsReferenceTypes() ? VERIFY_ERROR_BAD_CLASS_SOFT
+                                                           : VERIFY_ERROR_BAD_CLASS_HARD;
+        Fail(error) << "expected field " << PrettyField(field)
+                    << " to be compatible with type '" << insn_type
+                    << "' but found type '" << *field_type
+                    << "' in get-object";
         work_line_->SetRegisterType(this, vregA, reg_types_.Conflict());
         return;
       }
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index f2765e1..ca4ca35 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -20,4 +20,5 @@
 b/21614284
 b/21902684
 b/21863767
+b/21886894
 Done!
diff --git a/test/800-smali/smali/b_21886894.smali b/test/800-smali/smali/b_21886894.smali
new file mode 100644
index 0000000..f1ac3e9
--- /dev/null
+++ b/test/800-smali/smali/b_21886894.smali
@@ -0,0 +1,15 @@
+.class public LB21886894;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+    .registers 2
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.method public test()V
+    .registers 2
+    const v0, 0
+    iput-object v0, p0, Lsome/unresolved/Type;->a:I
+    return-void
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 2faee8f..8c9fda1 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -87,6 +87,8 @@
         testCases.add(new TestCase("b/21902684", "B21902684", "test", null, null, null));
         testCases.add(new TestCase("b/21863767", "B21863767", "run", null, null,
                 null));
+        testCases.add(new TestCase("b/21886894", "B21886894", "test", null, new VerifyError(),
+            null));
     }
 
     public void runTests() {