From b588f4c037d27dedeef358b478c281ebb3fbb900 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Tue, 26 May 2015 13:35:39 -0700 Subject: [PATCH] ART: Fix wrong hard-failure handling in verifier Correctly return null for the method when a hard failure is encountered. Also improve logging for order failures. Add a regression test. Bug: 20224106 (cherry picked from commit 3b74e275838729c5023cd80116f1b3b81306ee19) Change-Id: I6e08202617147378b204af169308b67fc69f92c6 --- runtime/verifier/method_verifier.cc | 15 ++++++++++++--- test/800-smali/expected.txt | 1 + test/800-smali/smali/b_20224106.smali | 16 ++++++++++++++++ test/800-smali/src/Main.java | 2 ++ 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 test/800-smali/smali/b_20224106.smali diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index f25e4ee70..9faaa4a57 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -2860,7 +2860,16 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { if (have_pending_hard_failure_) { if (Runtime::Current()->IsAotCompiler()) { /* When AOT compiling, check that the last failure is a hard failure */ - CHECK_EQ(failures_[failures_.size() - 1], VERIFY_ERROR_BAD_CLASS_HARD); + if (failures_[failures_.size() - 1] != VERIFY_ERROR_BAD_CLASS_HARD) { + LOG(ERROR) << "Pending failures:"; + for (auto& error : failures_) { + LOG(ERROR) << error; + } + for (auto& error_msg : failure_messages_) { + LOG(ERROR) << error_msg->str(); + } + LOG(FATAL) << "Pending hard failure, but last failure not hard."; + } } /* immediate failure, reject class */ info_messages_ << "Rejecting opcode " << inst->DumpString(dex_file_); @@ -3358,13 +3367,13 @@ ArtMethod* MethodVerifier::VerifyInvocationArgsFromIterator( if (!src_type.IsIntegralTypes()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "register v" << get_reg << " has type " << src_type << " but expected " << reg_type; - return res_method; + 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 res_method; + return nullptr; } } sig_registers += reg_type.IsLongOrDoubleTypes() ? 2 : 1; diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt index 5922257d0..a6b216bf3 100644 --- a/test/800-smali/expected.txt +++ b/test/800-smali/expected.txt @@ -15,4 +15,5 @@ b/18800943 (2) MoveExc MoveExceptionOnEntry EmptySparseSwitch +b/20224106 Done! diff --git a/test/800-smali/smali/b_20224106.smali b/test/800-smali/smali/b_20224106.smali new file mode 100644 index 000000000..78009dbc0 --- /dev/null +++ b/test/800-smali/smali/b_20224106.smali @@ -0,0 +1,16 @@ +.class public LB20224106; + +# Test that a hard + soft verifier failure in invoke-interface does not lead to +# an order abort (the last failure must be hard). + +.super Ljava/lang/Object; + +.method public static run(LB20224106;Ljava/lang/Object;)V + .registers 4 + # Two failure points here: + # 1) There is a parameter type mismatch. The formal type is integral (int), but the actual + # type is reference. + # 2) The receiver is not an interface or Object + invoke-interface {v2, v3}, Ljava/net/DatagramSocket;->checkPort(I)V + return-void +.end method diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java index 3e0b1f99e..3e8836408 100644 --- a/test/800-smali/src/Main.java +++ b/test/800-smali/src/Main.java @@ -79,6 +79,8 @@ public class Main { "moveExceptionOnEntry", new Object[]{0}, new VerifyError(), null)); testCases.add(new TestCase("EmptySparseSwitch", "EmptySparseSwitch", "run", null, null, null)); + testCases.add(new TestCase("b/20224106", "B20224106", "run", null, new VerifyError(), + 0)); } public void runTests() { -- 2.11.0