ART: Correctly hard-fail method with undefined register
In case a return-object gets an undefined return value register
and an unresolved return type, the "undefined" must take precedence
and lead to a hard fail of the method.
Bug: 22045582
Change-Id: Id5595a72331cd6272aa9ebc8ff3b9cea046294a2
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 5d685da..3c808de 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -1790,9 +1790,13 @@
DCHECK(!return_type.IsUninitializedReference());
const uint32_t vregA = inst->VRegA_11x();
const RegType& reg_type = work_line_->GetRegisterType(this, vregA);
- // Disallow returning uninitialized values and verify that the reference in vAA is an
- // instance of the "return_type"
- if (reg_type.IsUninitializedTypes()) {
+ // Disallow returning undefined, conflict & uninitialized values and verify that the
+ // reference in vAA is an instance of the "return_type."
+ if (reg_type.IsUndefined()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning undefined register";
+ } else if (reg_type.IsConflict()) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning register with conflict";
+ } else if (reg_type.IsUninitializedTypes()) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "returning uninitialized object '"
<< reg_type << "'";
} else if (!return_type.IsAssignableFrom(reg_type)) {
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index c762603..9413c13 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -21,4 +21,7 @@
b/21873167
b/21614284
b/21902684
+b/22045582
+b/22045582 (int)
+b/22045582 (wide)
Done!
diff --git a/test/800-smali/smali/b_22045582.smali b/test/800-smali/smali/b_22045582.smali
new file mode 100644
index 0000000..3cb661a
--- /dev/null
+++ b/test/800-smali/smali/b_22045582.smali
@@ -0,0 +1,13 @@
+.class public LB22045582;
+
+# Fail verification of a method that returns an undefined register even if the return type
+# is unresolved.
+
+.super Ljava/lang/Object;
+
+.method public static run()La/b/c/d/e/nonexistant;
+ .registers 4
+ # v1 is undefined, and the return type cannot be resolved. The Undefined should take
+ # precedence here.
+ return-object v1
+.end method
diff --git a/test/800-smali/smali/b_22045582_int.smali b/test/800-smali/smali/b_22045582_int.smali
new file mode 100644
index 0000000..c79bb30
--- /dev/null
+++ b/test/800-smali/smali/b_22045582_int.smali
@@ -0,0 +1,11 @@
+.class public LB22045582Int;
+
+# Fail verification of a method that returns an undefined integral register.
+
+.super Ljava/lang/Object;
+
+.method public static run()I
+ .registers 4
+ # v1 is undefined here.
+ return v1
+.end method
diff --git a/test/800-smali/smali/b_22045582_wide.smali b/test/800-smali/smali/b_22045582_wide.smali
new file mode 100644
index 0000000..1485000
--- /dev/null
+++ b/test/800-smali/smali/b_22045582_wide.smali
@@ -0,0 +1,11 @@
+.class public LB22045582Wide;
+
+# Fail verification of a method that returns an undefined wide register.
+
+.super Ljava/lang/Object;
+
+.method public static run()J
+ .registers 4
+ # v0/v1 is undefined here.
+ return-wide v0
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 7280d45..28954f8 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -89,6 +89,12 @@
testCases.add(new TestCase("b/21614284", "B21614284", "test", new Object[] { null },
new NullPointerException(), null));
testCases.add(new TestCase("b/21902684", "B21902684", "test", null, null, null));
+ testCases.add(new TestCase("b/22045582", "B22045582", "run", null, new VerifyError(),
+ 0));
+ testCases.add(new TestCase("b/22045582 (int)", "B22045582Int", "run", null,
+ new VerifyError(), 0));
+ testCases.add(new TestCase("b/22045582 (wide)", "B22045582Wide", "run", null,
+ new VerifyError(), 0));
}
public void runTests() {