diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2022-09-06 16:44:28 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-09-08 04:41:15 +0000 |
commit | 0d543c2213936f061b9bb6bd32dbd96bd1e8f902 (patch) | |
tree | c889c7c7bbe2b56f11e8dff86a4dee4b0afb752a | |
parent | e8240ffe2adcbc57b725dc3d726317451a7e9324 (diff) |
Fix access to destroyed QtJniTypes::String object
Doing
const char *value = QtJniTypes::className<Foo>();
is the same as doing
const char *value = qstring.toUtf8().constData();
The object owning the data is temporary, and destroyed at the end of the
statement. 'value' becomes a dangling pointer.
With QtJniTypes::String we have the extra problem that strings of
different lengths are different types, so we can't return different ones
from non-template functions. Instead, we have to make a deep copy of the
data into a QByteArray, and then operate on that.
This defeats the purpose of having compile-time string generation in the
first place, but fixes the immediate issue.
A follow-up commit can turn the valueForStaticField helper into a
template function that makes full use of compile-time generated
strings. However, this requires changes in the calling code as well.
Amends 70afc6721d4331fec0e9ccbb580d7c8b3ce5ec04.
Change-Id: I206d58f3a34700042782b77f9a28aa3a61520439
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
(cherry picked from commit 3d69e7ee4fa5f9b486a072fdc1ba6f697144351b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/bluetooth/android/jni_android.cpp | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp index 6392c07e..b01bbff6 100644 --- a/src/bluetooth/android/jni_android.cpp +++ b/src/bluetooth/android/jni_android.cpp @@ -38,25 +38,29 @@ static const char * const javaExtraUuid = "EXTRA_UUID"; * This function operates on the assumption that each * field is of type java/lang/String. */ +inline QByteArray classNameForStaticField(JavaNames javaName) +{ + switch (javaName) { + case JavaNames::BluetoothAdapter: { + constexpr auto cn = QtJniTypes::className<QtJniTypes::BluetoothAdapter>(); + return QByteArray(cn.data(), cn.size()); + } + case JavaNames::BluetoothDevice: { + constexpr auto cn = QtJniTypes::className<QtJniTypes::BluetoothDevice>(); + return QByteArray(cn.data(), cn.size()); + } + default: + break; + } + return {}; +} + QJniObject valueForStaticField(JavaNames javaName, JavaNames javaFieldName) { //construct key //the switch statements are used to reduce the number of duplicated strings //in the library - const char* className; - switch (javaName) { - case JavaNames::BluetoothAdapter: - className = QtJniTypes::className<QtJniTypes::BluetoothAdapter>(); - break; - case JavaNames::BluetoothDevice: - className = QtJniTypes::className<QtJniTypes::BluetoothDevice>(); - break; - default: - qCWarning(QT_BT_ANDROID) << "Unknown java class name passed to valueForStaticField():" << javaName; - return QJniObject(); - } - const char *fieldName; switch (javaFieldName) { case JavaNames::ActionAclConnected: @@ -94,12 +98,13 @@ QJniObject valueForStaticField(JavaNames javaName, JavaNames javaFieldName) return QJniObject(); } - const size_t offset_class = qstrlen(className); - const size_t offset_field = qstrlen(fieldName); - QByteArray key(qsizetype(offset_class + offset_field), Qt::Uninitialized); - memcpy(key.data(), className, offset_class); - memcpy(key.data()+offset_class, fieldName, offset_field); + const QByteArray className = classNameForStaticField(javaName); + if (className.isEmpty()) { + qCWarning(QT_BT_ANDROID) << "Unknown java class name passed to valueForStaticField():" << javaName; + return QJniObject(); + } + const QByteArray key = className + fieldName; JCachedStringFields::iterator it = cachedStringFields()->find(key); if (it == cachedStringFields()->end()) { QJniEnvironment env; |