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_common.h | |
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_common.h')
-rw-r--r-- | runtime/interpreter/interpreter_common.h | 23 |
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 |