From: Andreas Gampe Date: Fri, 18 Jul 2014 22:41:00 +0000 (-0700) Subject: ART: Also accept java.lang.Throwable as a catch-all handler. X-Git-Tag: android-x86-6.0-r1~145^2~2568^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f021cc085ac00ee2b6eaac6ffdf8f01596289dc7;p=android-x86%2Fart.git ART: Also accept java.lang.Throwable as a catch-all handler. Accept catch handlers with catch type of java.lang.Throwable as catch-all handlers. (cherry picked from commit f91baf17ad11a86c84c9fc34ff70feee65a43233) Bug: 16308310 Change-Id: Ie9b9582ee71c94c82b7695dc6f9c2c6df3d869d8 --- diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 8464b13fd..c0e4ae79a 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -2772,12 +2772,30 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { * "try" block when they throw, control transfers out of the method.) */ if ((opcode_flags & Instruction::kThrow) != 0 && insn_flags_[work_insn_idx_].IsInTry()) { - bool within_catch_all = false; + bool has_catch_all_handler = false; CatchHandlerIterator iterator(*code_item_, work_insn_idx_); + // Need the linker to try and resolve the handled class to check if it's Throwable. + ClassLinker* linker = Runtime::Current()->GetClassLinker(); + for (; iterator.HasNext(); iterator.Next()) { - if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) { - within_catch_all = true; + uint16_t handler_type_idx = iterator.GetHandlerTypeIndex(); + if (handler_type_idx == DexFile::kDexNoIndex16) { + has_catch_all_handler = true; + } else { + // It is also a catch-all if it is java.lang.Throwable. + mirror::Class* klass = linker->ResolveType(*dex_file_, handler_type_idx, *dex_cache_, + *class_loader_); + if (klass != nullptr) { + if (klass == mirror::Throwable::GetJavaLangThrowable()) { + has_catch_all_handler = true; + } + } else { + // Clear exception. + Thread* self = Thread::Current(); + DCHECK(self->IsExceptionPending()); + self->ClearException(); + } } /* * Merge registers into the "catch" block. We want to use the "savedRegs" rather than @@ -2793,7 +2811,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { * If the monitor stack depth is nonzero, there must be a "catch all" handler for this * instruction. This does apply to monitor-exit because of async exception handling. */ - if (work_line_->MonitorStackDepth() > 0 && !within_catch_all) { + if (work_line_->MonitorStackDepth() > 0 && !has_catch_all_handler) { /* * The state in work_line reflects the post-execution state. If the current instruction is a * monitor-enter and the monitor stack was empty, we don't need a catch-all (if it throws,