summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-06-26 17:33:47 -0700
committerAndreas Gampe <agampe@google.com>2015-06-26 17:40:23 -0700
commit3ae8da0a803370be9dd410226438f636af553e22 (patch)
tree346c8f1ba2abc9a2f6af283d4abcefc1f4de7f06 /runtime
parentffd43f62c23d2cbf84ab549dc37ca1dda2ac438d (diff)
downloadart-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.cc24
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);