Merge pull request #1501 from simophin/SES-2009-blinded-conversation

[SES-2009] Fix crashes on blinded conversation
release-1.18.4
Andrew 1 month ago committed by GitHub
commit c0912bbe6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,5 +1,6 @@
#include "config_base.h" #include "config_base.h"
#include "util.h" #include "util.h"
#include "jni_utils.h"
extern "C" { extern "C" {
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
@ -85,29 +86,34 @@ Java_network_loki_messenger_libsession_1util_ConfigBase_confirmPushed(JNIEnv *en
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_ConfigBase_merge___3Lkotlin_Pair_2(JNIEnv *env, jobject thiz, Java_network_loki_messenger_libsession_1util_ConfigBase_merge___3Lkotlin_Pair_2(JNIEnv *env, jobject thiz,
jobjectArray to_merge) { jobjectArray to_merge) {
std::lock_guard lock{util::util_mutex_}; return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto conf = ptrToConfigBase(env, thiz); std::lock_guard lock{util::util_mutex_};
size_t number = env->GetArrayLength(to_merge); auto conf = ptrToConfigBase(env, thiz);
std::vector<std::pair<std::string,session::ustring>> configs = {}; size_t number = env->GetArrayLength(to_merge);
for (int i = 0; i < number; i++) { std::vector<std::pair<std::string, session::ustring>> configs = {};
auto jElement = (jobject) env->GetObjectArrayElement(to_merge, i); for (int i = 0; i < number; i++) {
auto pair = extractHashAndData(env, jElement); auto jElement = (jobject) env->GetObjectArrayElement(to_merge, i);
configs.push_back(pair); auto pair = extractHashAndData(env, jElement);
} configs.push_back(pair);
auto returned = conf->merge(configs); }
auto string_stack = util::build_string_stack(env, returned); auto returned = conf->merge(configs);
return string_stack; auto string_stack = util::build_string_stack(env, returned);
return string_stack;
});
} }
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_ConfigBase_merge__Lkotlin_Pair_2(JNIEnv *env, jobject thiz, Java_network_loki_messenger_libsession_1util_ConfigBase_merge__Lkotlin_Pair_2(JNIEnv *env, jobject thiz,
jobject to_merge) { jobject to_merge) {
std::lock_guard lock{util::util_mutex_}; return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto conf = ptrToConfigBase(env, thiz); std::lock_guard lock{util::util_mutex_};
std::vector<std::pair<std::string, session::ustring>> configs = {extractHashAndData(env, to_merge)}; auto conf = ptrToConfigBase(env, thiz);
auto returned = conf->merge(configs); std::vector<std::pair<std::string, session::ustring>> configs = {
auto string_stack = util::build_string_stack(env, returned); extractHashAndData(env, to_merge)};
return string_stack; auto returned = conf->merge(configs);
auto string_stack = util::build_string_stack(env, returned);
return string_stack;
});
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop

@ -1,100 +1,121 @@
#include "contacts.h" #include "contacts.h"
#include "util.h" #include "util.h"
#include "jni_utils.h"
extern "C" extern "C"
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_Contacts_get(JNIEnv *env, jobject thiz, Java_network_loki_messenger_libsession_1util_Contacts_get(JNIEnv *env, jobject thiz,
jstring session_id) { jstring session_id) {
std::lock_guard lock{util::util_mutex_}; // If an exception is thrown, return nullptr
auto contacts = ptrToContacts(env, thiz); return jni_utils::run_catching_cxx_exception_or<jobject>(
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); [=]() -> jobject {
auto contact = contacts->get(session_id_chars); std::lock_guard lock{util::util_mutex_};
env->ReleaseStringUTFChars(session_id, session_id_chars); auto contacts = ptrToContacts(env, thiz);
if (!contact) return nullptr; auto session_id_chars = env->GetStringUTFChars(session_id, nullptr);
jobject j_contact = serialize_contact(env, contact.value()); auto contact = contacts->get(session_id_chars);
return j_contact; 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" extern "C"
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_Contacts_getOrConstruct(JNIEnv *env, jobject thiz, Java_network_loki_messenger_libsession_1util_Contacts_getOrConstruct(JNIEnv *env, jobject thiz,
jstring session_id) { jstring session_id) {
std::lock_guard lock{util::util_mutex_}; return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto contacts = ptrToContacts(env, thiz); std::lock_guard lock{util::util_mutex_};
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); auto contacts = ptrToContacts(env, thiz);
auto contact = contacts->get_or_construct(session_id_chars); auto session_id_chars = env->GetStringUTFChars(session_id, nullptr);
env->ReleaseStringUTFChars(session_id, session_id_chars); auto contact = contacts->get_or_construct(session_id_chars);
return serialize_contact(env, contact); env->ReleaseStringUTFChars(session_id, session_id_chars);
return serialize_contact(env, contact);
});
} }
extern "C" extern "C"
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_messenger_libsession_1util_Contacts_set(JNIEnv *env, jobject thiz, Java_network_loki_messenger_libsession_1util_Contacts_set(JNIEnv *env, jobject thiz,
jobject contact) { jobject contact) {
std::lock_guard lock{util::util_mutex_}; jni_utils::run_catching_cxx_exception_or_throws<void>(env, [=] {
auto contacts = ptrToContacts(env, thiz); std::lock_guard lock{util::util_mutex_};
auto contact_info = deserialize_contact(env, contact, contacts); auto contacts = ptrToContacts(env, thiz);
contacts->set(contact_info); auto contact_info = deserialize_contact(env, contact, contacts);
contacts->set(contact_info);
});
} }
extern "C" extern "C"
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_messenger_libsession_1util_Contacts_erase(JNIEnv *env, jobject thiz, Java_network_loki_messenger_libsession_1util_Contacts_erase(JNIEnv *env, jobject thiz,
jstring session_id) { jstring session_id) {
std::lock_guard lock{util::util_mutex_}; return jni_utils::run_catching_cxx_exception_or_throws<jboolean>(env, [=] {
auto contacts = ptrToContacts(env, thiz); std::lock_guard lock{util::util_mutex_};
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr); auto contacts = ptrToContacts(env, thiz);
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr);
bool result = contacts->erase(session_id_chars); bool result = contacts->erase(session_id_chars);
env->ReleaseStringUTFChars(session_id, session_id_chars); env->ReleaseStringUTFChars(session_id, session_id_chars);
return result; return result;
});
} }
extern "C" extern "C"
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma ide diagnostic ignored "bugprone-reserved-identifier" #pragma ide diagnostic ignored "bugprone-reserved-identifier"
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B(JNIEnv *env, Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B(JNIEnv *env,
jobject thiz, jobject thiz,
jbyteArray ed25519_secret_key) { jbyteArray ed25519_secret_key) {
std::lock_guard lock{util::util_mutex_}; return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); std::lock_guard lock{util::util_mutex_};
auto* contacts = new session::config::Contacts(secret_key, std::nullopt); 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"); jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts");
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V"); jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V");
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(contacts)); jobject newConfig = env->NewObject(contactsClass, constructor,
reinterpret_cast<jlong>(contacts));
return newConfig; return newConfig;
});
} }
extern "C" extern "C"
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B_3B( Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B_3B(
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) { JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) {
std::lock_guard lock{util::util_mutex_}; return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key); std::lock_guard lock{util::util_mutex_};
auto initial = util::ustring_from_bytes(env, initial_dump); 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"); jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts");
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V"); jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V");
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(contacts)); jobject newConfig = env->NewObject(contactsClass, constructor,
reinterpret_cast<jlong>(contacts));
return newConfig; return newConfig;
});
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop
extern "C" extern "C"
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_Contacts_all(JNIEnv *env, jobject thiz) { Java_network_loki_messenger_libsession_1util_Contacts_all(JNIEnv *env, jobject thiz) {
std::lock_guard lock{util::util_mutex_}; return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto contacts = ptrToContacts(env, thiz); std::lock_guard lock{util::util_mutex_};
jclass stack = env->FindClass("java/util/Stack"); auto contacts = ptrToContacts(env, thiz);
jmethodID init = env->GetMethodID(stack, "<init>", "()V"); jclass stack = env->FindClass("java/util/Stack");
jobject our_stack = env->NewObject(stack, init); jmethodID init = env->GetMethodID(stack, "<init>", "()V");
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;"); jobject our_stack = env->NewObject(stack, init);
for (const auto& contact : *contacts) { jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
auto contact_obj = serialize_contact(env, contact); for (const auto &contact: *contacts) {
env->CallObjectMethod(our_stack, push, contact_obj); auto contact_obj = serialize_contact(env, contact);
} env->CallObjectMethod(our_stack, push, contact_obj);
return our_stack; }
return our_stack;
});
} }

@ -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
Loading…
Cancel
Save