summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2022-09-06 16:44:28 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-09-08 04:41:15 +0000
commit0d543c2213936f061b9bb6bd32dbd96bd1e8f902 (patch)
treec889c7c7bbe2b56f11e8dff86a4dee4b0afb752a
parente8240ffe2adcbc57b725dc3d726317451a7e9324 (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.cpp41
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;