summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/verifier/method_verifier.cc33
-rw-r--r--test/004-JniTest/src/Main.java40
-rw-r--r--test/MyClassNatives/MyClassNatives.java9
3 files changed, 75 insertions, 7 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 248431de61..6c0d794636 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -951,6 +951,39 @@ bool MethodVerifier<kVerifierDebug>::Verify() {
return false;
}
+ // Test FastNative and CriticalNative annotations. We do this in the
+ // verifier for convenience.
+ if ((method_access_flags_ & kAccNative) != 0) {
+ // Fetch the flags from the annotations: the class linker hasn't processed
+ // them yet.
+ uint32_t native_access_flags = annotations::GetNativeMethodAnnotationAccessFlags(
+ *dex_file_, class_def_, dex_method_idx_);
+ if ((native_access_flags & kAccFastNative) != 0) {
+ if ((method_access_flags_ & kAccSynchronized) != 0) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "fast native methods cannot be synchronized";
+ return false;
+ }
+ }
+ if ((native_access_flags & kAccCriticalNative) != 0) {
+ if ((method_access_flags_ & kAccSynchronized) != 0) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "critical native methods cannot be synchronized";
+ return false;
+ }
+ if ((method_access_flags_ & kAccStatic) == 0) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "critical native methods must be static";
+ return false;
+ }
+ const char* shorty = dex_file_->GetMethodShorty(method_id);
+ for (size_t i = 0, len = strlen(shorty); i < len; ++i) {
+ if (Primitive::GetType(shorty[i]) == Primitive::kPrimNot) {
+ Fail(VERIFY_ERROR_BAD_CLASS_HARD) <<
+ "critical native methods must not have references as arguments or return type";
+ return false;
+ }
+ }
+ }
+ }
+
// This should have been rejected by the dex file verifier. Only do in debug build.
// Note: the above will also be rejected in the dex file verifier, starting in dex version 37.
if (kIsDebugBuild) {
diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java
index 5ec70d40d0..1539b9e0bc 100644
--- a/test/004-JniTest/src/Main.java
+++ b/test/004-JniTest/src/Main.java
@@ -66,6 +66,8 @@ public class Main {
testDoubleLoad(args[0]);
testUTFRegion("\0\0\0");
+
+ testBadFastCriticalNatives();
}
static class ABC { public static int XYZ = 12; }
@@ -420,6 +422,24 @@ public class Main {
throw new RuntimeException(t);
}
}
+
+ private static void testBadFastCriticalNatives() {
+ testBadFastCriticalNative("BadFastNative");
+ testBadFastCriticalNative("BadCriticalNative");
+ testBadFastCriticalNative("BadCriticalNative2");
+ testBadFastCriticalNative("BadCriticalNative3");
+ }
+
+ private static void testBadFastCriticalNative(String className) {
+ try {
+ Class.forName(className);
+ throw new Error("Expected verification error");
+ } catch (VerifyError e) {
+ // Expected.
+ } catch (Throwable e) {
+ throw new Error("Expected verification error");
+ }
+ }
}
@FunctionalInterface
@@ -466,3 +486,23 @@ class JniCallNonvirtualTestSubclass extends JniCallNonvirtualTest {
nonstaticMethodSubCalled = true;
}
}
+
+class BadFastNative {
+ @FastNative
+ public static native synchronized void test();
+}
+
+class BadCriticalNative {
+ @CriticalNative
+ public static native synchronized void test();
+}
+
+class BadCriticalNative2 {
+ @CriticalNative
+ public native void test();
+}
+
+class BadCriticalNative3 {
+ @CriticalNative
+ public static native void test(Object o);
+}
diff --git a/test/MyClassNatives/MyClassNatives.java b/test/MyClassNatives/MyClassNatives.java
index 3d939d6612..463fe3fafa 100644
--- a/test/MyClassNatives/MyClassNatives.java
+++ b/test/MyClassNatives/MyClassNatives.java
@@ -20,8 +20,7 @@ import dalvik.annotation.optimization.FastNative;
/*
* AUTOMATICALLY GENERATED FROM art/tools/mako-source-generator/...../MyClassNatives.java.mako
*
- * !!! DO NOT EDIT DIRECTLY !!!
- *
+ * The tool is however not available, so the changes now need to be done by hand.
*/
class MyClassNatives {
@@ -176,8 +175,6 @@ class MyClassNatives {
@FastNative
native double fooDD_Fast(double x, double y);
@FastNative
- synchronized native long fooJJ_synchronized_Fast(long x, long y);
- @FastNative
native Object fooIOO_Fast(int x, Object y, Object z);
@FastNative
static native Object fooSIOO_Fast(int x, Object y, Object z);
@@ -186,15 +183,13 @@ class MyClassNatives {
@FastNative
static native double fooSDD_Fast(double x, double y);
@FastNative
- static synchronized native Object fooSSIOO_Fast(int x, Object y, Object z);
- @FastNative
static native void arraycopy_Fast(Object src, int src_pos, Object dst, int dst_pos, int length);
@FastNative
native boolean compareAndSwapInt_Fast(Object obj, long offset, int expected, int newval);
@FastNative
static native int getText_Fast(long val1, Object obj1, long val2, Object obj2);
@FastNative
- synchronized native Object[] getSinkPropertiesNative_Fast(String path);
+ native Object[] getSinkPropertiesNative_Fast(String path);
@FastNative
native Class<?> instanceMethodThatShouldReturnClass_Fast();