diff options
| -rw-r--r-- | runtime/verifier/method_verifier.cc | 33 | ||||
| -rw-r--r-- | test/004-JniTest/src/Main.java | 40 | ||||
| -rw-r--r-- | test/MyClassNatives/MyClassNatives.java | 9 |
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(); |