summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter_common.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_common.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_common.cc')
-rw-r--r--runtime/interpreter/interpreter_common.cc22
1 files changed, 22 insertions, 0 deletions
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 86a6aea..36b250c 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -22,6 +22,7 @@ namespace interpreter {
template<InvokeType type, bool is_range, bool do_access_check>
bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
const Instruction* inst, JValue* result) {
+ bool do_assignability_check = do_access_check;
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
Object* receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
@@ -61,6 +62,10 @@ bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
++cur_reg;
}
+ const DexFile::TypeList* params;
+ if (do_assignability_check) {
+ params = mh.GetParameterTypeList();
+ }
size_t arg_offset = (receiver == NULL) ? 0 : 1;
const char* shorty = mh.GetShorty();
uint32_t arg[5];
@@ -73,6 +78,23 @@ bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
switch (shorty[shorty_pos + 1]) {
case 'L': {
Object* o = shadow_frame.GetVRegReference(arg_pos);
+ if (do_assignability_check && o != NULL) {
+ Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_);
+ if (arg_type == NULL) {
+ CHECK(self->IsExceptionPending());
+ return false;
+ }
+ if (!o->VerifierInstanceOf(arg_type)) {
+ // This should never happen.
+ self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+ "Ljava/lang/VirtualMachineError;",
+ "Invoking %s with bad arg %d, type '%s' not instance of '%s'",
+ mh.GetName(), shorty_pos,
+ ClassHelper(o->GetClass()).GetDescriptor(),
+ ClassHelper(arg_type).GetDescriptor());
+ return false;
+ }
+ }
new_shadow_frame->SetVRegReference(cur_reg, o);
break;
}