Fix crash in QDBusDemarshaller QStringList extraction

QDBusArgument QStringList extraction operator and QDBusDemarshaller that
implements the extraction do not check the type of the extracted value.
When extracting a QStringList and the value actually is e.g. an array of
bytes the string list extraction will crash as it interprets the bytes as
char pointers.

The fix adds DBus type checks to QDBusArgument QStringList extraction
operator implementations.
The checks are as permissive as possible provided crashes are avoided.

Task-number: QTBUG-22840
Change-Id: I4b67d75b59c5052d939f3a69f3e92dabdb3bdd6b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Sami Rosendahl 2011-12-05 13:06:40 +02:00 committed by Qt by Nokia
parent 8f19f14274
commit b4398dc4e3
3 changed files with 64 additions and 2 deletions

View File

@ -212,6 +212,7 @@ private:
QString toStringUnchecked();
QDBusObjectPath toObjectPathUnchecked();
QDBusSignature toSignatureUnchecked();
QStringList toStringListUnchecked();
};
inline QDBusMarshaller *QDBusArgumentPrivate::marshaller()

View File

@ -274,7 +274,7 @@ QVariant QDBusDemarshaller::toVariantInternal()
// QByteArray
return toByteArray();
case DBUS_TYPE_STRING:
return toStringList();
return toStringListUnchecked();
case DBUS_TYPE_DICT_ENTRY:
return QVariant::fromValue(duplicate());
@ -317,7 +317,7 @@ bool QDBusDemarshaller::isCurrentTypeStringLike()
}
}
QStringList QDBusDemarshaller::toStringList()
QStringList QDBusDemarshaller::toStringListUnchecked()
{
QStringList list;
@ -330,6 +330,15 @@ QStringList QDBusDemarshaller::toStringList()
return list;
}
QStringList QDBusDemarshaller::toStringList()
{
if (q_dbus_message_iter_get_arg_type(&iterator) == DBUS_TYPE_ARRAY
&& q_dbus_message_iter_get_element_type(&iterator) == DBUS_TYPE_STRING)
return toStringListUnchecked();
else
return QStringList();
}
QByteArray QDBusDemarshaller::toByteArray()
{
DBusMessageIter sub;

View File

@ -99,6 +99,9 @@ private slots:
void demarshallStrings_data();
void demarshallStrings();
void demarshallInvalidStringList_data();
void demarshallInvalidStringList();
private:
int fileDescriptorForTest();
@ -1375,5 +1378,54 @@ void tst_QDBusMarshall::demarshallStrings()
QVERIFY(receiveArg.atEnd());
}
void tst_QDBusMarshall::demarshallInvalidStringList_data()
{
addBasicTypesColumns();
// None of the basic types should demarshall to a string list
basicNumericTypes_data();
basicStringTypes_data();
// Arrays of non-string type should not demarshall to a string list
QList<bool> bools;
QTest::newRow("emptyboollist") << qVariantFromValue(bools);
bools << false << true << false;
QTest::newRow("boollist") << qVariantFromValue(bools);
// Structures should not demarshall to a QByteArray
QTest::newRow("struct of strings")
<< qVariantFromValue(QVariantList() << QString("foo") << QString("bar"));
QTest::newRow("struct of mixed types")
<< qVariantFromValue(QVariantList() << QString("foo") << int(42) << double(3.14));
}
void tst_QDBusMarshall::demarshallInvalidStringList()
{
QFETCH(QVariant, value);
QDBusConnection con = QDBusConnection::sessionBus();
QVERIFY(con.isConnected());
QDBusMessage msg = QDBusMessage::createMethodCall(serviceName, objectPath,
interfaceName, "ping");
QDBusArgument sendArg;
sendArg.beginStructure();
sendArg.appendVariant(value);
sendArg.endStructure();
msg.setArguments(QVariantList() << qVariantFromValue(sendArg));
QDBusMessage reply = con.call(msg);
const QDBusArgument receiveArg = qvariant_cast<QDBusArgument>(reply.arguments().at(0));
receiveArg.beginStructure();
QStringList receiveValue;
receiveArg >> receiveValue;
QCOMPARE(receiveValue, QStringList());
receiveArg.endStructure();
QVERIFY(receiveArg.atEnd());
}
QTEST_MAIN(tst_QDBusMarshall)
#include "tst_qdbusmarshall.moc"