ART: Fix invalid access and DCHECK in verifier
If we get a throwing failure when setting types from the signature,
the work instruction index is still invalid. Do not try to copy the
line then.
As a throwing failure might happen in the above instance, but the
flow analysis expects to have a cleared failure flag before processing
each instruction, clear the flag.
Bug: 21645819
Bug: 22080519
(cherry picked from commit 3ae8da0a803370be9dd410226438f636af553e22)
Change-Id: I224c4dad98fa5bb50e62210f0ee30c0dd020e3a6
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 02929e8..8a8b455 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -385,7 +385,7 @@
bool allow_thread_suspension)
: self_(self),
reg_types_(can_load_classes),
- work_insn_idx_(-1),
+ work_insn_idx_(DexFile::kDexNoIndex),
dex_method_idx_(dex_method_idx),
mirror_method_(method),
method_access_flags_(method_access_flags),
@@ -409,7 +409,8 @@
has_check_casts_(false),
has_virtual_or_interface_invokes_(false),
verify_to_dump_(verify_to_dump),
- allow_thread_suspension_(allow_thread_suspension) {
+ allow_thread_suspension_(allow_thread_suspension),
+ link_(nullptr) {
self->PushVerifier(this);
DCHECK(class_def != nullptr);
}
@@ -600,12 +601,16 @@
// We need to save the work_line if the instruction wasn't throwing before. Otherwise we'll
// try to merge garbage.
// Note: this assumes that Fail is called before we do any work_line modifications.
- const uint16_t* insns = code_item_->insns_ + work_insn_idx_;
- const Instruction* inst = Instruction::At(insns);
- int opcode_flags = Instruction::FlagsOf(inst->Opcode());
+ // Note: this can fail before we touch any instruction, for the signature of a method. So
+ // add a check.
+ if (work_insn_idx_ < DexFile::kDexNoIndex) {
+ const uint16_t* insns = code_item_->insns_ + work_insn_idx_;
+ const Instruction* inst = Instruction::At(insns);
+ int opcode_flags = Instruction::FlagsOf(inst->Opcode());
- if ((opcode_flags & Instruction::kThrow) == 0 && CurrentInsnFlags()->IsInTry()) {
- saved_line_->CopyFromLine(work_line_.get());
+ if ((opcode_flags & Instruction::kThrow) == 0 && CurrentInsnFlags()->IsInTry()) {
+ saved_line_->CopyFromLine(work_line_.get());
+ }
}
}
break;
@@ -1237,6 +1242,9 @@
PrependToLastFailMessage(prepend);
return false;
}
+ // We may have a runtime failure here, clear.
+ have_pending_runtime_throw_failure_ = false;
+
/* Perform code flow verification. */
if (!CodeFlowVerifyMethod()) {
DCHECK_NE(failures_.size(), 0U);