diff options
author | Jeff Hao <jeffhao@google.com> | 2013-09-03 19:07:00 -0700 |
---|---|---|
committer | Jeff Hao <jeffhao@google.com> | 2013-09-24 15:18:36 -0700 |
commit | a3faaf4bece7f42529c013fe87bd41de59798656 (patch) | |
tree | 933e312a4aa4d69b2d7da7eda4d592419cec4729 /runtime/interpreter/interpreter_switch_impl.cc | |
parent | a9a624b2be2180e6bd33f02c89fb8521376a2e8c (diff) | |
download | art-a3faaf4bece7f42529c013fe87bd41de59798656.zip art-a3faaf4bece7f42529c013fe87bd41de59798656.tar.gz art-a3faaf4bece7f42529c013fe87bd41de59798656.tar.bz2 |
Fix handling of unresolved references in verifier.
The verifier should not treat use of unresolved references as a reason to reject
the entire class. Instead, the verifier treats the instruction as a throw. If
that class is run, the interpreter with extra checks will throw an exception.
Bug: 10457426
Change-Id: I3799da843a7ffb3519bbf6dc13a6276519d9cb95
Diffstat (limited to 'runtime/interpreter/interpreter_switch_impl.cc')
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl.cc | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc index d49807c..2d658b3 100644 --- a/runtime/interpreter/interpreter_switch_impl.cc +++ b/runtime/interpreter/interpreter_switch_impl.cc @@ -53,6 +53,7 @@ namespace interpreter { template<bool do_access_check> static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register) { + bool do_assignability_check = do_access_check; if (UNLIKELY(!shadow_frame.HasReferenceArray())) { LOG(FATAL) << "Invalid shadow frame for interpreter use"; return JValue(); @@ -226,11 +227,28 @@ static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::C case Instruction::RETURN_OBJECT: { PREAMBLE(); JValue result; + Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data)); result.SetJ(0); - result.SetL(shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data))); + result.SetL(obj_result); if (UNLIKELY(self->TestAllFlags())) { CheckSuspend(self); } + if (do_assignability_check && obj_result != NULL) { + Class* return_type = MethodHelper(shadow_frame.GetMethod()).GetReturnType(); + if (return_type == NULL) { + // Return the pending exception. + HANDLE_PENDING_EXCEPTION(); + } + if (!obj_result->VerifierInstanceOf(return_type)) { + // This should never happen. + self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(), + "Ljava/lang/VirtualMachineError;", + "Returning '%s' that is not instance of return type '%s'", + ClassHelper(obj_result->GetClass()).GetDescriptor(), + ClassHelper(return_type).GetDescriptor()); + HANDLE_PENDING_EXCEPTION(); + } + } if (UNLIKELY(instrumentation->HasMethodExitListeners())) { instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), shadow_frame.GetMethod(), inst->GetDexPc(insns), @@ -472,6 +490,12 @@ static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::C Object* exception = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data)); if (UNLIKELY(exception == NULL)) { ThrowNullPointerException(NULL, "throw with null exception"); + } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) { + // This should never happen. + self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(), + "Ljava/lang/VirtualMachineError;", + "Throwing '%s' that is not instance of Throwable", + ClassHelper(exception->GetClass()).GetDescriptor()); } else { self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable()); } |