summaryrefslogtreecommitdiff
path: root/runtime/art_method.cc
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2022-07-06 10:01:58 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2022-07-07 16:58:21 +0000
commitd88c1499efe2f718f3cc1f45a3dc178471b22ce6 (patch)
treed28e20d9a4f87d2c1fc9a867b111cdc818ff250a /runtime/art_method.cc
parent4a21275dfb1bc58ede8141cbfd103ad46c3fcf2d (diff)
Fix one edge case at method linking to throw at runtime.
If we could not find a public implementation for a public method, throw an IllegalAccessError at runtime, when the method is actually called, instead of when the class is being created. Test: 840-resolution Test: 182-method-linking Change-Id: I741c7d0f6fc3b90a5d1614e1a9b76985a2eb32e2
Diffstat (limited to 'runtime/art_method.cc')
-rw-r--r--runtime/art_method.cc26
1 files changed, 25 insertions, 1 deletions
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index cef9d7b9bd..71f08e7b4d 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -150,10 +150,34 @@ uint16_t ArtMethod::FindObsoleteDexClassDefIndex() {
return dex_file->GetIndexForClassDef(*class_def);
}
-void ArtMethod::ThrowInvocationTimeError() {
+void ArtMethod::ThrowInvocationTimeError(ObjPtr<mirror::Object> receiver) {
DCHECK(!IsInvokable());
if (IsDefaultConflicting()) {
ThrowIncompatibleClassChangeErrorForMethodConflict(this);
+ } else if (GetDeclaringClass()->IsInterface() && receiver != nullptr) {
+ // If this was an interface call, check whether there is a method in the
+ // superclass chain that isn't public. In this situation, we should throw an
+ // IllegalAccessError.
+ DCHECK(IsAbstract());
+ ObjPtr<mirror::Class> current = receiver->GetClass();
+ while (current != nullptr) {
+ for (ArtMethod& method : current->GetDeclaredMethodsSlice(kRuntimePointerSize)) {
+ ArtMethod* np_method = method.GetInterfaceMethodIfProxy(kRuntimePointerSize);
+ if (!np_method->IsStatic() &&
+ np_method->GetNameView() == GetNameView() &&
+ np_method->GetSignature() == GetSignature()) {
+ if (!np_method->IsPublic()) {
+ ThrowIllegalAccessErrorForImplementingMethod(receiver->GetClass(), np_method, this);
+ return;
+ } else if (np_method->IsAbstract()) {
+ ThrowAbstractMethodError(this);
+ return;
+ }
+ }
+ }
+ current = current->GetSuperClass();
+ }
+ ThrowAbstractMethodError(this);
} else {
DCHECK(IsAbstract());
ThrowAbstractMethodError(this);