JNI: check for pending exception first in getCleanJniObject()

returning early if the object is null will not clear pending exceptions
from the previous failed JNI call, and that will crash the app on the
next jni call if an explicit exception clearing is not done, wish mostly
the case. Checking and clearing for exceptions has to always be done
under this call.

Fixes: QTBUG-122135
Change-Id: I0d42d012a4d1305fa07147fd22860d7c005f9b83
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
(cherry picked from commit 0a4599637657375517fcaf35177d8c7bac302556)
This commit is contained in:
Assam Boudjelthia 2024-03-22 01:21:09 +02:00
parent 32270a1276
commit 4444167c16
3 changed files with 31 additions and 5 deletions

View File

@ -346,11 +346,9 @@ static jclass getCachedClass(const QByteArray &className)
*/
static QJniObject getCleanJniObject(jobject object, JNIEnv *env)
{
if (!object)
return QJniObject();
if (QJniEnvironment::checkAndClearExceptions(env)) {
env->DeleteLocalRef(object);
if (QJniEnvironment::checkAndClearExceptions(env) || !object) {
if (object)
env->DeleteLocalRef(object);
return QJniObject();
}

View File

@ -319,4 +319,12 @@ public class QtJniObjectTestClass
{
return callbackWithDouble(value);
}
public Object callMethodThrowsException() throws Exception {
throw new Exception();
}
public static Object callStaticMethodThrowsException() throws Exception {
throw new Exception();
}
}

View File

@ -40,10 +40,12 @@ private slots:
void ctor();
void callMethodTest();
void callMethodThrowsException();
void callObjectMethodTest();
void stringConvertionTest();
void compareOperatorTests();
void className();
void callStaticMethodThrowsException();
void callStaticObjectMethodClassName();
void callStaticObjectMethod();
void callStaticObjectMethodById();
@ -262,6 +264,15 @@ void tst_QJniObject::callMethodTest()
}
}
void tst_QJniObject::callMethodThrowsException()
{
QtJniTypes::QtJniObjectTestClass instance;
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("java.lang.Exception"));
auto res = instance.callMethod<jobject>("callMethodThrowsException");
QVERIFY(!res.isValid());
QVERIFY(!QJniEnvironment().checkAndClearExceptions());
}
void tst_QJniObject::callObjectMethodTest()
{
const QString qString = QLatin1String("Hello, Java");
@ -339,6 +350,15 @@ void tst_QJniObject::className()
}
}
void tst_QJniObject::callStaticMethodThrowsException()
{
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("java.lang.Exception"));
auto res = QtJniTypes::QtJniObjectTestClass::callStaticMethod<jobject>(
"callStaticMethodThrowsException");
QVERIFY(!res.isValid());
QVERIFY(!QJniEnvironment().checkAndClearExceptions());
}
void tst_QJniObject::callStaticObjectMethodClassName()
{
QJniObject formatString = QJniObject::fromString(QLatin1String("test format"));