summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2015-06-23 17:45:21 +0100
committer Vladimir Marko <vmarko@google.com> 2015-06-25 10:46:07 +0100
commit414000ec4d728b5c85f8c6dee4f867fecde59b01 (patch)
treed4260308a2e6c5b2c14d64bd3c72b6df7061e614
parentbcc9d2b5f07afb6d7e83d71179c3069825a69d7c (diff)
Hard-fail get-/put-object to a non-reference field.
Bug: 21886894 Change-Id: Iec870c223ce97fd90dcce05ae80c002e2b24cb5d
-rw-r--r--runtime/verifier/method_verifier.cc26
-rw-r--r--test/800-smali/expected.txt1
-rw-r--r--test/800-smali/smali/b_21886894.smali15
-rw-r--r--test/800-smali/src/Main.java2
4 files changed, 36 insertions, 8 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 95b327e7fd..04fe35ebaa 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4060,10 +4060,15 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType&
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);
@@ -4087,10 +4092,15 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType&
}
} 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 9413c13aac..0d2087a216 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -24,4 +24,5 @@ b/21902684
b/22045582
b/22045582 (int)
b/22045582 (wide)
+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 0000000000..f1ac3e9ffc
--- /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 28954f8f90..14d2e43034 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -95,6 +95,8 @@ public class Main {
new VerifyError(), 0));
testCases.add(new TestCase("b/22045582 (wide)", "B22045582Wide", "run", null,
new VerifyError(), 0));
+ testCases.add(new TestCase("b/21886894", "B21886894", "test", null, new VerifyError(),
+ null));
}
public void runTests() {