summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter_goto_table_impl.cc
diff options
context:
space:
mode:
authorJeff Hao <jeffhao@google.com>2013-09-03 19:07:00 -0700
committerJeff Hao <jeffhao@google.com>2013-09-24 15:18:36 -0700
commita3faaf4bece7f42529c013fe87bd41de59798656 (patch)
tree933e312a4aa4d69b2d7da7eda4d592419cec4729 /runtime/interpreter/interpreter_goto_table_impl.cc
parenta9a624b2be2180e6bd33f02c89fb8521376a2e8c (diff)
downloadart-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_goto_table_impl.cc')
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc26
1 files changed, 25 insertions, 1 deletions
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index d70b80e..018add3 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -74,6 +74,7 @@ namespace interpreter {
template<bool do_access_check>
JValue ExecuteGotoImpl(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();
@@ -264,11 +265,28 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_INSTRUCTION_START(RETURN_OBJECT) {
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(), dex_pc,
@@ -512,6 +530,12 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
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());
}