diff options
| author | 2014-07-18 15:41:00 -0700 | |
|---|---|---|
| committer | 2014-07-18 16:38:31 -0700 | |
| commit | f91baf17ad11a86c84c9fc34ff70feee65a43233 (patch) | |
| tree | 9bd78c90b89cae8d7530690eec49564d0ef80faf | |
| parent | 031ddea20cb311dfdb3bd16a13750f9cb426b299 (diff) | |
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.
Bug: 16308310
Change-Id: Ie9b9582ee71c94c82b7695dc6f9c2c6df3d869d8
| -rw-r--r-- | runtime/verifier/method_verifier.cc | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index f1b5afd235..c8ee9b9f3a 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -2763,12 +2763,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 @@ -2784,7 +2802,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, |