forked from signalapp/Signal-Android
-
Notifications
You must be signed in to change notification settings - Fork 178
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1501 from simophin/SES-2009-blinded-conversation
[SES-2009] Fix crashes on blinded conversation
- Loading branch information
Showing
3 changed files
with
151 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,121 @@ | ||
#include "contacts.h" | ||
#include "util.h" | ||
#include "jni_utils.h" | ||
|
||
extern "C" | ||
JNIEXPORT jobject JNICALL | ||
Java_network_loki_messenger_libsession_1util_Contacts_get(JNIEnv *env, jobject thiz, | ||
jstring session_id) { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); | ||
auto contact = contacts->get(session_id_chars); | ||
env->ReleaseStringUTFChars(session_id, session_id_chars); | ||
if (!contact) return nullptr; | ||
jobject j_contact = serialize_contact(env, contact.value()); | ||
return j_contact; | ||
// If an exception is thrown, return nullptr | ||
return jni_utils::run_catching_cxx_exception_or<jobject>( | ||
[=]() -> jobject { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); | ||
auto contact = contacts->get(session_id_chars); | ||
env->ReleaseStringUTFChars(session_id, session_id_chars); | ||
if (!contact) return nullptr; | ||
jobject j_contact = serialize_contact(env, contact.value()); | ||
return j_contact; | ||
}, | ||
[](const char *) -> jobject { return nullptr; } | ||
); | ||
} | ||
|
||
extern "C" | ||
JNIEXPORT jobject JNICALL | ||
Java_network_loki_messenger_libsession_1util_Contacts_getOrConstruct(JNIEnv *env, jobject thiz, | ||
jstring session_id) { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); | ||
auto contact = contacts->get_or_construct(session_id_chars); | ||
env->ReleaseStringUTFChars(session_id, session_id_chars); | ||
return serialize_contact(env, contact); | ||
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); | ||
auto contact = contacts->get_or_construct(session_id_chars); | ||
env->ReleaseStringUTFChars(session_id, session_id_chars); | ||
return serialize_contact(env, contact); | ||
}); | ||
} | ||
|
||
extern "C" | ||
JNIEXPORT void JNICALL | ||
Java_network_loki_messenger_libsession_1util_Contacts_set(JNIEnv *env, jobject thiz, | ||
jobject contact) { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto contact_info = deserialize_contact(env, contact, contacts); | ||
contacts->set(contact_info); | ||
jni_utils::run_catching_cxx_exception_or_throws<void>(env, [=] { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto contact_info = deserialize_contact(env, contact, contacts); | ||
contacts->set(contact_info); | ||
}); | ||
} | ||
|
||
extern "C" | ||
JNIEXPORT jboolean JNICALL | ||
Java_network_loki_messenger_libsession_1util_Contacts_erase(JNIEnv *env, jobject thiz, | ||
jstring session_id) { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); | ||
return jni_utils::run_catching_cxx_exception_or_throws<jboolean>(env, [=] { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); | ||
|
||
bool result = contacts->erase(session_id_chars); | ||
env->ReleaseStringUTFChars(session_id, session_id_chars); | ||
return result; | ||
bool result = contacts->erase(session_id_chars); | ||
env->ReleaseStringUTFChars(session_id, session_id_chars); | ||
return result; | ||
}); | ||
} | ||
extern "C" | ||
#pragma clang diagnostic push | ||
#pragma ide diagnostic ignored "bugprone-reserved-identifier" | ||
JNIEXPORT jobject JNICALL | ||
Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B(JNIEnv *env, | ||
jobject thiz, | ||
jbyteArray ed25519_secret_key) { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); | ||
auto* contacts = new session::config::Contacts(secret_key, std::nullopt); | ||
jobject thiz, | ||
jbyteArray ed25519_secret_key) { | ||
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); | ||
auto *contacts = new session::config::Contacts(secret_key, std::nullopt); | ||
|
||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts"); | ||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V"); | ||
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(contacts)); | ||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts"); | ||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V"); | ||
jobject newConfig = env->NewObject(contactsClass, constructor, | ||
reinterpret_cast<jlong>(contacts)); | ||
|
||
return newConfig; | ||
return newConfig; | ||
}); | ||
} | ||
extern "C" | ||
JNIEXPORT jobject JNICALL | ||
Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B_3B( | ||
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); | ||
auto initial = util::ustring_from_bytes(env, initial_dump); | ||
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); | ||
auto initial = util::ustring_from_bytes(env, initial_dump); | ||
|
||
auto* contacts = new session::config::Contacts(secret_key, initial); | ||
auto *contacts = new session::config::Contacts(secret_key, initial); | ||
|
||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts"); | ||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V"); | ||
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(contacts)); | ||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts"); | ||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V"); | ||
jobject newConfig = env->NewObject(contactsClass, constructor, | ||
reinterpret_cast<jlong>(contacts)); | ||
|
||
return newConfig; | ||
return newConfig; | ||
}); | ||
} | ||
#pragma clang diagnostic pop | ||
extern "C" | ||
JNIEXPORT jobject JNICALL | ||
Java_network_loki_messenger_libsession_1util_Contacts_all(JNIEnv *env, jobject thiz) { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
jclass stack = env->FindClass("java/util/Stack"); | ||
jmethodID init = env->GetMethodID(stack, "<init>", "()V"); | ||
jobject our_stack = env->NewObject(stack, init); | ||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;"); | ||
for (const auto& contact : *contacts) { | ||
auto contact_obj = serialize_contact(env, contact); | ||
env->CallObjectMethod(our_stack, push, contact_obj); | ||
} | ||
return our_stack; | ||
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] { | ||
std::lock_guard lock{util::util_mutex_}; | ||
auto contacts = ptrToContacts(env, thiz); | ||
jclass stack = env->FindClass("java/util/Stack"); | ||
jmethodID init = env->GetMethodID(stack, "<init>", "()V"); | ||
jobject our_stack = env->NewObject(stack, init); | ||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;"); | ||
for (const auto &contact: *contacts) { | ||
auto contact_obj = serialize_contact(env, contact); | ||
env->CallObjectMethod(our_stack, push, contact_obj); | ||
} | ||
return our_stack; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#ifndef SESSION_ANDROID_JNI_UTILS_H | ||
#define SESSION_ANDROID_JNI_UTILS_H | ||
|
||
#include <jni.h> | ||
#include <exception> | ||
|
||
namespace jni_utils { | ||
/** | ||
* Run a C++ function and catch any exceptions, throwing a Java exception if one is caught, | ||
* and returning a default-constructed value of the specified type. | ||
* | ||
* @tparam RetT The return type of the function | ||
* @tparam Func The function type | ||
* @param f The function to run | ||
* @param fallbackRun The function to run if an exception is caught. The optional exception message reference will be passed to this function. | ||
* @return The return value of the function, or the return value of the fallback function if an exception was caught | ||
*/ | ||
template<class RetT, class Func, class FallbackRun> | ||
RetT run_catching_cxx_exception_or(Func f, FallbackRun fallbackRun) { | ||
try { | ||
return f(); | ||
} catch (const std::exception &e) { | ||
return fallbackRun(e.what()); | ||
} catch (...) { | ||
return fallbackRun(nullptr); | ||
} | ||
} | ||
|
||
/** | ||
* Run a C++ function and catch any exceptions, throwing a Java exception if one is caught. | ||
* | ||
* @tparam RetT The return type of the function | ||
* @tparam Func The function type | ||
* @param env The JNI environment | ||
* @param f The function to run | ||
* @return The return value of the function, or a default-constructed value of the specified type if an exception was caught | ||
*/ | ||
template<class RetT, class Func> | ||
RetT run_catching_cxx_exception_or_throws(JNIEnv *env, Func f) { | ||
return run_catching_cxx_exception_or<RetT>(f, [env](const char *msg) { | ||
jclass exceptionClass = env->FindClass("java/lang/RuntimeException"); | ||
if (msg) { | ||
auto formatted_message = std::string("libsession: C++ exception: ") + msg; | ||
env->ThrowNew(exceptionClass, formatted_message.c_str()); | ||
} else { | ||
env->ThrowNew(exceptionClass, "libsession: Unknown C++ exception"); | ||
} | ||
|
||
return RetT(); | ||
}); | ||
} | ||
} | ||
|
||
#endif //SESSION_ANDROID_JNI_UTILS_H |