diff options
author | Andreas Gampe <agampe@google.com> | 2015-06-26 17:33:47 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-06-26 17:40:23 -0700 |
commit | 3ae8da0a803370be9dd410226438f636af553e22 (patch) | |
tree | 346c8f1ba2abc9a2f6af283d4abcefc1f4de7f06 /runtime | |
parent | ffd43f62c23d2cbf84ab549dc37ca1dda2ac438d (diff) | |
download | art-3ae8da0a803370be9dd410226438f636af553e22.zip art-3ae8da0a803370be9dd410226438f636af553e22.tar.gz art-3ae8da0a803370be9dd410226438f636af553e22.tar.bz2 |
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
Change-Id: I224c4dad98fa5bb50e62210f0ee30c0dd020e3a6
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/verifier/method_verifier.cc | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 1f7dd58..085f741 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -385,7 +385,7 @@ MethodVerifier::MethodVerifier(Thread* self, 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 @@ MethodVerifier::MethodVerifier(Thread* self, 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); } @@ -599,12 +600,16 @@ std::ostream& MethodVerifier::Fail(VerifyError error) { // 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()); - - if ((opcode_flags & Instruction::kThrow) == 0 && CurrentInsnFlags()->IsInTry()) { - saved_line_->CopyFromLine(work_line_.get()); + // 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()); + } } } break; @@ -1236,6 +1241,9 @@ bool MethodVerifier::VerifyCodeFlow() { 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); |