diff options
| -rw-r--r-- | runtime/jni_internal.cc | 24 | ||||
| -rw-r--r-- | runtime/jni_internal_test.cc | 28 |
2 files changed, 48 insertions, 4 deletions
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 0624281c20..845691d182 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -112,6 +112,17 @@ static void ThrowNoSuchMethodError(ScopedObjectAccess& soa, mirror::Class* c, kind, c->GetDescriptor().c_str(), name, sig); } +static void ReportInvalidJNINativeMethod(const ScopedObjectAccess& soa, mirror::Class* c, + const char* kind, jint idx, bool return_errors) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + LOG(return_errors ? ERROR : FATAL) << "Failed to register native method in " + << PrettyDescriptor(c) << " in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8() + << ": " << kind << " is null at index " << idx; + ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow(); + soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchMethodError;", + "%s is null at index %d", kind, idx); +} + static mirror::Class* EnsureInitialized(Thread* self, mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (LIKELY(klass->IsInitialized())) { @@ -2357,6 +2368,17 @@ class JNI { for (jint i = 0; i < method_count; ++i) { const char* name = methods[i].name; const char* sig = methods[i].signature; + const void* fnPtr = methods[i].fnPtr; + if (UNLIKELY(name == nullptr)) { + ReportInvalidJNINativeMethod(soa, c, "method name", i, return_errors); + return JNI_ERR; + } else if (UNLIKELY(sig == nullptr)) { + ReportInvalidJNINativeMethod(soa, c, "method signature", i, return_errors); + return JNI_ERR; + } else if (UNLIKELY(fnPtr == nullptr)) { + ReportInvalidJNINativeMethod(soa, c, "native function", i, return_errors); + return JNI_ERR; + } bool is_fast = false; if (*sig == '!') { is_fast = true; @@ -2384,7 +2406,7 @@ class JNI { VLOG(jni) << "[Registering JNI native method " << PrettyMethod(m) << "]"; - m->RegisterNative(soa.Self(), methods[i].fnPtr, is_fast); + m->RegisterNative(soa.Self(), fnPtr, is_fast); } return JNI_OK; } diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index d50e094627..8ef1cb6115 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -432,27 +432,49 @@ static void BogusMethod() { TEST_F(JniInternalTest, RegisterAndUnregisterNatives) { jclass jlobject = env_->FindClass("java/lang/Object"); jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError"); + void* native_function = reinterpret_cast<void*>(BogusMethod); // Sanity check that no exceptions are pending. ASSERT_FALSE(env_->ExceptionCheck()); + // Check that registering method without name causes a NoSuchMethodError. + { + JNINativeMethod methods[] = { { nullptr, "()V", native_function } }; + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); + } + ExpectException(jlnsme); + + // Check that registering method without signature causes a NoSuchMethodError. + { + JNINativeMethod methods[] = { { "notify", nullptr, native_function } }; + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); + } + ExpectException(jlnsme); + + // Check that registering method without function causes a NoSuchMethodError. + { + JNINativeMethod methods[] = { { "notify", "()V", nullptr } }; + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); + } + ExpectException(jlnsme); + // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError. { - JNINativeMethod methods[] = { { "foo", "()V", nullptr } }; + JNINativeMethod methods[] = { { "foo", "()V", native_function } }; EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); } ExpectException(jlnsme); // Check that registering non-native methods causes a NoSuchMethodError. { - JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", nullptr } }; + JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", native_function } }; EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); } ExpectException(jlnsme); // Check that registering native methods is successful. { - JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } }; + JNINativeMethod methods[] = { { "notify", "()V", native_function } }; EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK); } EXPECT_FALSE(env_->ExceptionCheck()); |