JNI: don't access null jobject
When Java calls a native function that expects a QString with a null String object, then we get a nullptr jstring. We must not try to convert that to a QString. Add the necessary checks at the call-site of the toQString helper, and an assert to the helper itself. Add test case. Change-Id: If5c55c702bdb3f89ac45fdf3912af2ac295f5e5c Reviewed-by: Volker Krause <vkrause@kde.org> (cherry picked from commit db6a9834d2b109e81cc73ef3c64d0c420237e9dc) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
6dc19b55fc
commit
11b9657b08
@ -819,12 +819,14 @@ public:
|
||||
container.reserve(sz);
|
||||
if constexpr (std::is_same_v<typename ContainerType::value_type, QString>) {
|
||||
for (auto element : *this) {
|
||||
if constexpr (std::is_same_v<decltype(element), QString>)
|
||||
if constexpr (std::is_same_v<decltype(element), QString>) {
|
||||
container.emplace_back(element);
|
||||
else if constexpr (std::is_same_v<decltype(element), jstring>)
|
||||
container.emplace_back(QtJniTypes::Detail::toQString(element, env));
|
||||
else
|
||||
} else if constexpr (std::is_same_v<decltype(element), jstring>) {
|
||||
container.emplace_back(element ? QtJniTypes::Detail::toQString(element, env)
|
||||
: QString{});
|
||||
} else {
|
||||
container.emplace_back(QJniObject(element).toString());
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_base_of_v<std::remove_pointer_t<jobject>, std::remove_pointer_t<T>>) {
|
||||
for (auto element : *this)
|
||||
|
@ -163,7 +163,7 @@ struct JNITypeForArgImpl<QString>
|
||||
|
||||
static QString fromVarArg(Type t)
|
||||
{
|
||||
return QtJniTypes::Detail::toQString(t, QJniEnvironment::getJniEnv());
|
||||
return t ? QtJniTypes::Detail::toQString(t, QJniEnvironment::getJniEnv()) : QString();
|
||||
}
|
||||
};
|
||||
|
||||
@ -190,7 +190,7 @@ public:
|
||||
|
||||
static QList<T> fromVarArg(Type t)
|
||||
{
|
||||
return QJniArray<ElementType>(t).toContainer();
|
||||
return t ? QJniArray<ElementType>(t).toContainer() : QList<T>{};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,7 @@ static inline jstring fromQString(const QString &string, JNIEnv *env)
|
||||
|
||||
static inline QString toQString(jstring string, JNIEnv *env)
|
||||
{
|
||||
Q_ASSERT(string);
|
||||
const jsize length = env->GetStringLength(string);
|
||||
QString res(length, Qt::Uninitialized);
|
||||
env->GetStringRegion(string, 0, length, reinterpret_cast<jchar *>(res.data()));
|
||||
|
@ -307,6 +307,7 @@ public class QtJniObjectTestClass
|
||||
native public int callbackWithRawArray(Object[] value);
|
||||
native public int callbackWithQList(double[] value);
|
||||
native public int callbackWithStringList(String[] value);
|
||||
native public int callbackWithNull(String str);
|
||||
|
||||
public int callMeBackWithObject(QtJniObjectTestClass that)
|
||||
{
|
||||
@ -358,6 +359,10 @@ public class QtJniObjectTestClass
|
||||
{
|
||||
return callbackWithStringList(value);
|
||||
}
|
||||
public int callMeBackWithNull()
|
||||
{
|
||||
return callbackWithNull(null);
|
||||
}
|
||||
|
||||
public Object callMethodThrowsException() throws Exception {
|
||||
throw new Exception();
|
||||
|
@ -1959,6 +1959,7 @@ enum class CallbackParameterType
|
||||
RawArray,
|
||||
QList,
|
||||
QStringList,
|
||||
Null,
|
||||
};
|
||||
|
||||
static std::optional<TestClass> calledWithObject;
|
||||
@ -2047,6 +2048,14 @@ static int callbackWithStringList(JNIEnv *, jobject, const QStringList &value)
|
||||
}
|
||||
Q_DECLARE_JNI_NATIVE_METHOD(callbackWithStringList)
|
||||
|
||||
static std::optional<QString> calledWithNull;
|
||||
static int callbackWithNull(JNIEnv *, jobject, const QString &str)
|
||||
{
|
||||
calledWithNull.emplace(str);
|
||||
return int(CallbackParameterType::Null);
|
||||
}
|
||||
Q_DECLARE_JNI_NATIVE_METHOD(callbackWithNull)
|
||||
|
||||
void tst_QJniObject::callback_data()
|
||||
{
|
||||
QTest::addColumn<CallbackParameterType>("parameterType");
|
||||
@ -2062,6 +2071,7 @@ void tst_QJniObject::callback_data()
|
||||
QTest::addRow("RawArray") << CallbackParameterType::RawArray;
|
||||
QTest::addRow("QList") << CallbackParameterType::QList;
|
||||
QTest::addRow("QStringList") << CallbackParameterType::QStringList;
|
||||
QTest::addRow("Null") << CallbackParameterType::Null;
|
||||
}
|
||||
|
||||
void tst_QJniObject::callback()
|
||||
@ -2171,6 +2181,15 @@ void tst_QJniObject::callback()
|
||||
QCOMPARE(calledWithStringList.value(), strings);
|
||||
break;
|
||||
}
|
||||
case CallbackParameterType::Null: {
|
||||
QVERIFY(TestClass::registerNativeMethods({
|
||||
Q_JNI_NATIVE_METHOD(callbackWithNull)
|
||||
}));
|
||||
result = testObject.callMethod<int>("callMeBackWithNull");
|
||||
QVERIFY(calledWithNull);
|
||||
QCOMPARE(calledWithNull.value(), QString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
QCOMPARE(result, int(parameterType));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user