Add defensive check for result returned after JNI function calls

Summary:
Added method which checks if value(methodId, fieldId, class ...) returned by JNI functions (getMethod, getField, getClass ...) is valid or not and throw exception if they are not valid

##Changelog:
[Internal][Yoga] Add defensive check for result returned after JNI calls

Reviewed By: astreet

Differential Revision: D18745718

fbshipit-source-id: 2af26eda15fbe7834e1c9b274deeed4f106274ab
This commit is contained in:
Sidharth Guglani
2019-12-02 05:21:56 -08:00
committed by Facebook Github Bot
parent 073f49d0d0
commit ac8eb111a9
3 changed files with 22 additions and 7 deletions

View File

@@ -18,11 +18,11 @@ void registerNatives(
size_t numMethods) { size_t numMethods) {
jclass clazz = env->FindClass(className); jclass clazz = env->FindClass(className);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !clazz);
env->RegisterNatives(clazz, methods, numMethods); auto result = env->RegisterNatives(clazz, methods, numMethods);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, result != JNI_OK);
} }
jmethodID getStaticMethodId( jmethodID getStaticMethodId(
@@ -32,7 +32,7 @@ jmethodID getStaticMethodId(
const char* methodDescriptor) { const char* methodDescriptor) {
jmethodID methodId = jmethodID methodId =
env->GetStaticMethodID(clazz, methodName, methodDescriptor); env->GetStaticMethodID(clazz, methodName, methodDescriptor);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !methodId);
return methodId; return methodId;
} }
@@ -42,7 +42,7 @@ jmethodID getMethodId(
const char* methodName, const char* methodName,
const char* methodDescriptor) { const char* methodDescriptor) {
jmethodID methodId = env->GetMethodID(clazz, methodName, methodDescriptor); jmethodID methodId = env->GetMethodID(clazz, methodName, methodDescriptor);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !methodId);
return methodId; return methodId;
} }
@@ -52,7 +52,7 @@ jfieldID getFieldId(
const char* fieldName, const char* fieldName,
const char* fieldSignature) { const char* fieldSignature) {
jfieldID fieldId = env->GetFieldID(clazz, fieldName, fieldSignature); jfieldID fieldId = env->GetFieldID(clazz, fieldName, fieldSignature);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !fieldId);
return fieldId; return fieldId;
} }
@@ -83,7 +83,7 @@ callStaticObjectMethod(JNIEnv* env, jclass clazz, jmethodID methodId, ...) {
va_start(args, methodId); va_start(args, methodId);
jobject result = env->CallStaticObjectMethodV(clazz, methodId, args); jobject result = env->CallStaticObjectMethodV(clazz, methodId, args);
va_end(args); va_end(args);
assertNoPendingJniException(env); assertNoPendingJniExceptionIf(env, !result);
return make_local_ref(env, result); return make_local_ref(env, result);
} }

View File

@@ -76,6 +76,19 @@ void assertNoPendingJniException(JNIEnv* env) {
throw YogaJniException(throwable); throw YogaJniException(throwable);
} }
void assertNoPendingJniExceptionIf(JNIEnv* env, bool condition) {
if (!condition) {
return;
}
if (env->ExceptionCheck() == JNI_TRUE) {
assertNoPendingJniException(env);
return;
}
throw YogaJniException();
}
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook

View File

@@ -47,6 +47,8 @@ void logErrorMessageAndDie(const char* message);
*/ */
void assertNoPendingJniException(JNIEnv* env); void assertNoPendingJniException(JNIEnv* env);
void assertNoPendingJniExceptionIf(JNIEnv* env, bool condition);
} // namespace vanillajni } // namespace vanillajni
} // namespace yoga } // namespace yoga
} // namespace facebook } // namespace facebook