diff options
author | 2016-10-20 18:50:24 +0000 | |
---|---|---|
committer | 2016-10-20 18:50:25 +0000 | |
commit | fc5fbfc13fd6873d42fe82c308ee68a685258b4c (patch) | |
tree | d68edb92308bc83f8097a2fd8ef651500f183fa9 /runtime/class_linker.cc | |
parent | eb6b620b8e3366fbe5e26ad6fe7651f0585e9686 (diff) | |
parent | c7a420c95376953ecb3bd84b0ac2e245e90d827c (diff) |
Merge "Ensure that overrides work in presence of package-private methods."
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index a7d8b13014..cea8377c58 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -5643,27 +5643,29 @@ X86_OPTNONE bool ClassLinker::LinkVirtualMethods( for (size_t j = 0; j < super_vtable_length; ++j) { // Search the hash table to see if we are overridden by any method. ArtMethod* super_method = vtable->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_); + if (!klass->CanAccessMember(super_method->GetDeclaringClass(), + super_method->GetAccessFlags())) { + // Continue on to the next method since this one is package private and canot be overridden. + // Before Android 4.1, the package-private method super_method might have been incorrectly + // overridden. + continue; + } MethodNameAndSignatureComparator super_method_name_comparator( super_method->GetInterfaceMethodIfProxy(image_pointer_size_)); + // We remove the method so that subsequent lookups will be faster by making the hash-map + // smaller as we go on. uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator); if (hash_index != hash_table.GetNotFoundIndex()) { ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking( hash_index, image_pointer_size_); - if (klass->CanAccessMember(super_method->GetDeclaringClass(), - super_method->GetAccessFlags())) { - if (super_method->IsFinal()) { - ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s", - ArtMethod::PrettyMethod(virtual_method).c_str(), - super_method->GetDeclaringClassDescriptor()); - return false; - } - vtable->SetElementPtrSize(j, virtual_method, image_pointer_size_); - virtual_method->SetMethodIndex(j); - } else { - LOG(WARNING) << "Before Android 4.1, method " << ArtMethod::PrettyMethod(virtual_method) - << " would have incorrectly overridden the package-private method in " - << PrettyDescriptor(super_method->GetDeclaringClassDescriptor()); + if (super_method->IsFinal()) { + ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s", + virtual_method->PrettyMethod().c_str(), + super_method->GetDeclaringClassDescriptor()); + return false; } + vtable->SetElementPtrSize(j, virtual_method, image_pointer_size_); + virtual_method->SetMethodIndex(j); } else if (super_method->IsOverridableByDefaultMethod()) { // We didn't directly override this method but we might through default methods... // Check for default method update. @@ -6458,15 +6460,20 @@ static void CheckVTableHasNoDuplicates(Thread* self, } MethodNameAndSignatureComparator name_comparator( vtable_entry->GetInterfaceMethodIfProxy(pointer_size)); - for (int32_t j = i+1; j < num_entries; j++) { + for (int32_t j = i + 1; j < num_entries; j++) { ArtMethod* other_entry = vtable->GetElementPtrSize<ArtMethod*>(j, pointer_size); + if (!klass->CanAccessMember(other_entry->GetDeclaringClass(), + other_entry->GetAccessFlags())) { + continue; + } CHECK(vtable_entry != other_entry && !name_comparator.HasSameNameAndSignature( other_entry->GetInterfaceMethodIfProxy(pointer_size))) << "vtable entries " << i << " and " << j << " are identical for " - << klass->PrettyClass() << " in method " - << vtable_entry->PrettyMethod() - << " and " << other_entry->PrettyMethod(); + << klass->PrettyClass() << " in method " << vtable_entry->PrettyMethod() << " (0x" + << std::hex << reinterpret_cast<uintptr_t>(vtable_entry) << ") and " + << other_entry->PrettyMethod() << " (0x" << std::hex + << reinterpret_cast<uintptr_t>(other_entry) << ")"; } } } |