Verify method invocation type.
Dalvik provides five different ways to invoke a method (virtual, super,
direct, static, interface). Using a virtual invoke instruction to call
a direct method will not produce the desired results.
This adds a test to the verifier that ensures the method targeted by
an invocation instruction is of an appropriate kind.
Bug 3082885.
Change-Id: Iacf14b9b3959a0894d89d727286e10e3ecf72680
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 933c058..dcd8252 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -1002,6 +1002,24 @@
}
/*
+ * See if the method matches the MethodType.
+ */
+static bool isCorrectInvokeKind(MethodType methodType, Method* resMethod)
+{
+ switch (methodType) {
+ case METHOD_DIRECT:
+ return dvmIsDirectMethod(resMethod);
+ case METHOD_STATIC:
+ return dvmIsStaticMethod(resMethod);
+ case METHOD_VIRTUAL:
+ case METHOD_INTERFACE:
+ return !dvmIsDirectMethod(resMethod);
+ default:
+ return false;
+ }
+}
+
+/*
* Verify the arguments to a method. We're executing in "method", making
* a call to the method reference in vB.
*
@@ -1060,10 +1078,9 @@
//char* curMethodDesc =
// dexProtoCopyMethodDescriptor(&meth->prototype);
- LOGI("Could not find method %s.%s, referenced from "
- "method %s.%s\n",
- dotMissingClass, methodName/*, methodDesc*/,
- dotMethClass, meth->name/*, curMethodDesc*/);
+ LOGI("Could not find method %s.%s, referenced from method %s.%s\n",
+ dotMissingClass, methodName/*, methodDesc*/,
+ dotMethClass, meth->name/*, curMethodDesc*/);
free(dotMissingClass);
free(dotMethClass);
@@ -1093,6 +1110,16 @@
}
/*
+ * See if the method type implied by the invoke instruction matches the
+ * access flags for the target method.
+ */
+ if (!isCorrectInvokeKind(methodType, resMethod)) {
+ LOG_VFY("VFY: invoke type does not match method type of %s.%s\n",
+ resMethod->clazz->descriptor, resMethod->name);
+ goto fail;
+ }
+
+ /*
* If we're using invoke-super(method), make sure that the executing
* method's class' superclass has a vtable entry for the target method.
*/