summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter_common.h
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.h
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.h')
-rw-r--r--runtime/interpreter/interpreter_common.h23
1 files changed, 20 insertions, 3 deletions
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index a6c5e62..3ad1935 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -215,6 +215,7 @@ static bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
const Instruction* inst, uint16_t inst_data) {
+ bool do_assignability_check = do_access_check;
bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
@@ -255,9 +256,24 @@ static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
case Primitive::kPrimLong:
f->SetLong(obj, shadow_frame.GetVRegLong(vregA));
break;
- case Primitive::kPrimNot:
- f->SetObj(obj, shadow_frame.GetVRegReference(vregA));
+ case Primitive::kPrimNot: {
+ Object* reg = shadow_frame.GetVRegReference(vregA);
+ if (do_assignability_check && reg != NULL) {
+ Class* field_class = FieldHelper(f).GetType();
+ if (!reg->VerifierInstanceOf(field_class)) {
+ // This should never happen.
+ self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+ "Ljava/lang/VirtualMachineError;",
+ "Put '%s' that is not instance of field '%s' in '%s'",
+ ClassHelper(reg->GetClass()).GetDescriptor(),
+ ClassHelper(field_class).GetDescriptor(),
+ ClassHelper(f->GetDeclaringClass()).GetDescriptor());
+ return false;
+ }
+ }
+ f->SetObj(obj, reg);
break;
+ }
default:
LOG(FATAL) << "Unreachable: " << field_type;
}
@@ -479,7 +495,8 @@ static void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh)
}
static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
- const uint32_t dex_pc, MethodHelper& mh) {
+ const uint32_t dex_pc, MethodHelper& mh)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const bool kTracing = false;
if (kTracing) {
#define TRACE_LOG std::cerr