summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaurice Kalinowski <maurice.kalinowski@qt.io>2023-11-26 10:49:04 +0100
committerMaurice Kalinowski <maurice.kalinowski@qt.io>2023-11-30 09:57:18 +0100
commit95b38eafb514832a951a5c67f3a2af9ff8fb83de (patch)
tree63bd10eab85ff49f57e3a2591832f76e1f014880
parent648a2da86537776b075e9e9062de5ae2deb1429d (diff)
Fix handling of multiple wildcards
The matching check for topic filters did not take into account that a mixture of wildcards is valid. While # is only allowed a single time, using + is valid in multiple occasions and can also me mixed with other wildcards. Fixes: QTBUG-104478 Pick-to: 6.6 6.5 6.2 Change-Id: I04129d5fbbb21c95115a15d74c6787804a8d0b10 Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r--src/mqtt/qmqtttopicfilter.cpp2
-rw-r--r--tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp32
-rw-r--r--tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp6
3 files changed, 39 insertions, 1 deletions
diff --git a/src/mqtt/qmqtttopicfilter.cpp b/src/mqtt/qmqtttopicfilter.cpp
index d6796f9..6c96ff8 100644
--- a/src/mqtt/qmqtttopicfilter.cpp
+++ b/src/mqtt/qmqtttopicfilter.cpp
@@ -223,7 +223,7 @@ bool QMqttTopicFilter::match(const QMqttTopicName &name, MatchOptions matchOptio
return false;
for (int i = 0; i < filterLevels.size(); ++i) {
- if (filterLevels.at(i) != topicLevels.at(i))
+ if (filterLevels.at(i) != topicLevels.at(i) && filterLevels.at(i) != QLatin1Char('+'))
return false;
}
return true;
diff --git a/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp b/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp
index bdb3e7d..b32dec3 100644
--- a/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp
+++ b/tests/auto/qmqttsubscription/tst_qmqttsubscription.cpp
@@ -30,6 +30,7 @@ private Q_SLOTS:
void noLocal_data();
void noLocal();
void qtbug_106203();
+ void qtbug_104478();
private:
void createAndSubscribe(QMqttClient *c, QMqttSubscription **sub, const QString &topic);
QProcess m_brokerProcess;
@@ -450,6 +451,37 @@ void Tst_QMqttSubscription::qtbug_106203()
QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect from broker.");
}
+void Tst_QMqttSubscription::qtbug_104478()
+{
+ QMqttClient client;
+ client.setHostname(m_testBroker);
+ client.setPort(m_port);
+
+ client.connectToHost();
+ QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
+
+ auto singleWildcardSub = client.subscribe(QLatin1String("test/+/+/test2"));
+ QTRY_VERIFY2(singleWildcardSub->state() == QMqttSubscription::Subscribed, "Could not subscribe to topic.");
+ QSignalSpy singleSpy(singleWildcardSub, SIGNAL(messageReceived(QMqttMessage)));
+
+ auto mixedWildcardSub = client.subscribe(QLatin1String("test/+/#"));
+ QTRY_VERIFY2(mixedWildcardSub->state() == QMqttSubscription::Subscribed, "Could not subscribe to topic.");
+ QSignalSpy mixedSpy(mixedWildcardSub, SIGNAL(messageReceived(QMqttMessage)));
+
+
+ const QString topic(QLatin1String("test/foo/bar/test2"));
+
+ QSignalSpy pubSpy(&client, SIGNAL(messageSent(qint32)));
+ client.publish(topic, "Wildcard checks", 1);
+ QTRY_VERIFY2(pubSpy.size() == 1, "Could not publish message.");
+
+ QTRY_VERIFY2(singleSpy.count() == 1, "Did not receive message");
+ QTRY_VERIFY2(mixedSpy.count() == 1, "Did not receive message");
+
+ client.disconnectFromHost();
+ QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect from broker.");
+}
+
QTEST_MAIN(Tst_QMqttSubscription)
#include "tst_qmqttsubscription.moc"
diff --git a/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp b/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp
index 925fb5c..dcd1c2f 100644
--- a/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp
+++ b/tests/auto/qmqtttopicfilter/tst_qmqtttopicfilter.cpp
@@ -83,6 +83,12 @@ void Tst_QMqttTopicFilter::matches()
QVERIFY(QMqttTopicFilter("/+").match(QMqttTopicName("/finance")));
QVERIFY(!QMqttTopicFilter("+").match(QMqttTopicName("/finance")));
+ // QTBUG-104478
+ filter = QMqttTopicFilter("sport/+/player1/#");
+ QVERIFY(filter.match(QMqttTopicName("sport/tennis/player1/ranking")));
+ filter = QMqttTopicFilter("sport/+/+");
+ QVERIFY(filter.match(QMqttTopicName("sport/tennis/player2")));
+
// Non normative comment's examples [4.7.2]
QVERIFY(QMqttTopicFilter("#").match(QMqttTopicName("$SYS/foo")));
QVERIFY(!QMqttTopicFilter("#").match(QMqttTopicName("$SYS/foo"), QMqttTopicFilter::WildcardsDontMatchDollarTopicMatchOption));