From a32210c53d23b73ba769053b8c1b214a7468fe6e Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Wed, 24 Jun 2015 10:26:13 -0700 Subject: [PATCH] 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 --- runtime/verifier/method_verifier.cc | 10 +++++++--- test/800-smali/expected.txt | 3 +++ test/800-smali/smali/b_22045582.smali | 13 +++++++++++++ test/800-smali/smali/b_22045582_int.smali | 11 +++++++++++ test/800-smali/smali/b_22045582_wide.smali | 11 +++++++++++ test/800-smali/src/Main.java | 6 ++++++ 6 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 test/800-smali/smali/b_22045582.smali create mode 100644 test/800-smali/smali/b_22045582_int.smali create mode 100644 test/800-smali/smali/b_22045582_wide.smali diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 5d685da54..3c808ded9 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -1790,9 +1790,13 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { 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 c762603e5..9413c13aa 100644 --- a/test/800-smali/expected.txt +++ b/test/800-smali/expected.txt @@ -21,4 +21,7 @@ b/21863767 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 000000000..3cb661a7c --- /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 000000000..c79bb3053 --- /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 000000000..1485000c2 --- /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 7280d45b8..28954f8f9 100644 --- a/test/800-smali/src/Main.java +++ b/test/800-smali/src/Main.java @@ -89,6 +89,12 @@ public class Main { 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() { -- 2.11.0