ART: Check invoke-interface earlier in verifier
Invoke-interface should only be called on an interface method.
Move the check earlier, as otherwise we'll try to resolve and
potentially inject a method into the dex cache.
Also templatize ResolveMethod with a version always checking
the invoke type, and on a cache miss check whether type target
type is an interface when an interface invoke type was given.
Bug: 21869691
Change-Id: Ica27158f675b5aa223d9229248189612f4706832
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index dccb1da..ba2fb94 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -68,7 +68,7 @@
class_loader.Assign(caller->GetClassLoader());
}
- return class_linker->ResolveMethod(
+ return class_linker->ResolveMethod<ClassLinker::kNoICCECheckForCache>(
*outer_method->GetDexFile(), method_index, dex_cache, class_loader, nullptr, invoke_type);
}
@@ -401,7 +401,10 @@
mirror::Object* null_this = nullptr;
HandleWrapper<mirror::Object> h_this(
hs.NewHandleWrapper(type == kStatic ? &null_this : this_object));
- resolved_method = class_linker->ResolveMethod(self, method_idx, referrer, type);
+ constexpr ClassLinker::ResolveMode resolve_mode =
+ access_check ? ClassLinker::kForceICCECheck
+ : ClassLinker::kNoICCECheckForCache;
+ resolved_method = class_linker->ResolveMethod<resolve_mode>(self, method_idx, referrer, type);
}
if (UNLIKELY(resolved_method == nullptr)) {
DCHECK(self->IsExceptionPending()); // Throw exception and unwind.