QtDBus: disallow sending method calls without destinations on a bus

QtDBus has allowed this because the bus would stop the message and
return it to us as an UnknownMethod. But it makes no sense to send it,
so let's block it early.

For practical purposes, this allows the tst_qdbusmarshall test to
continue working regardless of which daemon is running the bus. The
message it was checking against only came from dbus-daemon; for users of
systems now running dbus-broker (like my openSUSE Tumbleweed) the
message was different and the test was failing.

Pick-to: 6.8
Change-Id: Ia134ca414080cf243974fffd913fdad09d80cc60
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
This commit is contained in:
Thiago Macieira 2024-10-19 09:37:59 -07:00
parent f42f5b5614
commit d19db44d3f
4 changed files with 18 additions and 7 deletions

View File

@ -873,7 +873,9 @@ QString QDBusConnection::name() const
*/
QDBusConnection::ConnectionCapabilities QDBusConnection::connectionCapabilities() const
{
return d ? d->connectionCapabilities() : ConnectionCapabilities();
if (!d)
return {};
return d->connectionCapabilities() & ~QDBusConnectionPrivate::InternalCapabilitiesMask;
}
/*!

View File

@ -276,11 +276,18 @@ signals:
void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message);
public:
static constexpr QDBusConnection::ConnectionCapabilities ConnectionIsBus =
QDBusConnection::ConnectionCapabilities::fromInt(0x8000'0000);
static constexpr QDBusConnection::ConnectionCapabilities InternalCapabilitiesMask = ConnectionIsBus;
QAtomicInt ref;
QAtomicInt capabilities;
QDBusConnection::ConnectionCapabilities connectionCapabilities() const
{
return (QDBusConnection::ConnectionCapabilities)capabilities.loadRelaxed();
uint capa = capabilities.loadRelaxed();
if (mode == ClientMode)
capa |= ConnectionIsBus;
return QDBusConnection::ConnectionCapabilities(capa);
}
QString name; // this connection's name
QString baseService; // this connection's base service

View File

@ -109,7 +109,10 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB
case QDBusMessage::MethodCallMessage:
// only service and interface can be empty -> path and name must not be empty
if (!d_ptr->parametersValidated) {
if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
using namespace QDBusUtil;
AllowEmptyFlag serviceCheckMode = capabilities & QDBusConnectionPrivate::ConnectionIsBus
? EmptyNotAllowed : EmptyAllowed;
if (!checkBusName(d_ptr->service, serviceCheckMode, error))
return nullptr;
if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
return nullptr;
@ -146,7 +149,7 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB
}
break;
case QDBusMessage::SignalMessage:
// only the service name can be empty here
// only the service name can be empty here (even for bus connections)
if (!d_ptr->parametersValidated) {
if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
return nullptr;

View File

@ -933,10 +933,9 @@ void tst_QDBusMarshall::sendCallErrors_data()
QTest::addColumn<QString>("errorMsg");
QTest::addColumn<QString>("ignoreMsg");
// this error comes from the bus server
QTest::newRow("empty-service") << "" << objectPath << interfaceName << "ping" << QVariantList()
<< "org.freedesktop.DBus.Error.UnknownMethod"
<< "Method \"ping\" with signature \"\" on interface \"org.qtproject.autotests.qpong\" doesn't exist\n" << (const char*)0;
<< "org.qtproject.QtDBus.Error.InvalidService"
<< "Service name cannot be empty" << "";
QTest::newRow("invalid-service-single-label") << "service" << objectPath << interfaceName << "ping" << QVariantList()
<< "org.qtproject.QtDBus.Error.InvalidService"