diff options
-rw-r--r-- | src/class_linker.cc | 8 | ||||
-rw-r--r-- | src/dex_verifier.cc | 8 | ||||
-rw-r--r-- | src/object.h | 2 | ||||
-rw-r--r-- | src/runtime_support.cc | 19 |
4 files changed, 25 insertions, 12 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index dd8fc11f45..88016f4fe0 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -2183,11 +2183,13 @@ bool ClassLinker::LinkSuperClass(SirtRef<Class>& klass) { } // Verify if (super->IsFinal() || super->IsInterface()) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", + Thread* thread = Thread::Current(); + thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", "Superclass %s of %s is %s", PrettyDescriptor(super).c_str(), PrettyDescriptor(klass.get()).c_str(), super->IsFinal() ? "declared final" : "an interface"); + klass->SetVerifyErrorClass(thread->GetException()->GetClass()); return false; } if (!klass->CanAccess(super)) { @@ -2347,10 +2349,12 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> DCHECK(interface != NULL); if (!interface->IsInterface()) { ClassHelper ih(interface); - Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", + Thread* thread = Thread::Current(); + thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", "Class %s implements non-interface class %s", PrettyDescriptor(klass.get()).c_str(), PrettyDescriptor(ih.GetDescriptor()).c_str()); + klass->SetVerifyErrorClass(thread->GetException()->GetClass()); return false; } // Add this interface. diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc index 90940679d1..9ba5d34576 100644 --- a/src/dex_verifier.cc +++ b/src/dex_verifier.cc @@ -3085,8 +3085,8 @@ Method* DexVerifier::VerifyInvocationArgs(const Instruction::DecodedInstruction& (method_type == METHOD_STATIC && !res_method->IsStatic()) || ((method_type == METHOD_VIRTUAL || method_type == METHOD_INTERFACE) && res_method->IsDirect()) ) { - Fail(VERIFY_ERROR_GENERIC) << "invoke type does not match method type of " - << PrettyMethod(res_method); + Fail(VERIFY_ERROR_CLASS_CHANGE) << "invoke type does not match method type of " + << PrettyMethod(res_method); return NULL; } // If we're using invoke-super(method), make sure that the executing method's class' superclass @@ -3294,7 +3294,9 @@ void DexVerifier::VerifyAPut(const Instruction::DecodedInstruction& dec_insn, << " incompatible with aput of type " << insn_type; } else { // The instruction agrees with the type of array, confirm the value to be stored does too - work_line_->VerifyRegisterType(dec_insn.vA_, component_type); + // Note: we use the instruction type (rather than the component type) for aput-object as + // incompatible classes will be caught at runtime as an array store exception + work_line_->VerifyRegisterType(dec_insn.vA_, is_primitive ? component_type : insn_type); } } } diff --git a/src/object.h b/src/object.h index eb379876e1..80bb000354 100644 --- a/src/object.h +++ b/src/object.h @@ -1681,7 +1681,7 @@ class MANAGED Class : public StaticStorageBase { } void SetVerifyErrorClass(Class* klass) { - klass->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false); + SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false); } uint16_t GetDexTypeIndex() const { diff --git a/src/runtime_support.cc b/src/runtime_support.cc index 3a3eaf1f17..12226265cd 100644 --- a/src/runtime_support.cc +++ b/src/runtime_support.cc @@ -407,12 +407,19 @@ void* UnresolvedDirectMethodTrampolineFromCode(int32_t method_idx, Method** sp, // Resolve method filling in dex cache Method* called = linker->ResolveMethod(method_idx, *caller_sp, true); if (LIKELY(!thread->IsExceptionPending())) { - // Update CodeAndDirectMethod table - Method* caller = *caller_sp; - DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache(); - dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethod(method_idx, called); - // We got this far, ensure that the declaring class is initialized - linker->EnsureInitialized(called->GetDeclaringClass(), true); + if (LIKELY(called->IsDirect())) { + // Update CodeAndDirectMethod table + Method* caller = *caller_sp; + DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache(); + dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethod(method_idx, called); + // We got this far, ensure that the declaring class is initialized + linker->EnsureInitialized(called->GetDeclaringClass(), true); + } else { + // Direct method has been made virtual + thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", + "Expected direct method but found virtual: %s", + PrettyMethod(called, true).c_str()); + } } void* code; if (UNLIKELY(thread->IsExceptionPending())) { |