1
0
mirror of https://github.com/qt/qtmqtt.git synced 2026-10-25 16:16:26 +00:00
qtmqtt/tests
Tatiana Borisova 06d301aa50 Read the Remaining Length as a variable byte integer everywhere
- Every MQTT packet begins with a fixed header, whose second field is the
Remaining Length: the number of bytes that follow. It is not a byte. It
is spread over one to four bytes, seven value bits each, with the top
bit meaning "another byte follows". So values up to 127 take one byte,
and larger values take more.

Six packet types read it as a single quint8: SUBACK, UNSUBACK, PUBACK,
PUBREC, PUBREL and PUBCOMP. For most of them that used to be correct.
In MQTT 3.1.1 those packets contain nothing but a two byte identifier,
so the length was always exactly 2, which always fits in one byte. The
code did not even use the byte it read: it checked that the value was 2
and then hardcoded the length.

MQTT 5.0 support (ac66658) gave those packets an optional reason code
and properties, so the length can now be far above 127. That commit
switched off the "must be 2" check for MQTT 5.0 and began using the
byte as the real length, but kept reading only one byte. The check had
been the only thing making a one byte read safe, because a multi-byte
length always has its top bit set and so could never equal 2.

SUBACK never had a fixed length at all, since its payload carries one
reason code per subscribed topic filter. It has been misparsed for any
SUBACK above 127 bytes since the parser was written (d96011b).

Reading one byte of a two byte length consumes one byte too few, so the
remainder of the packet is then read as the next packet's header. The
client rejects a valid acknowledgement and stays out of step for the
rest of the connection. Brokers trigger this on ordinary traffic as
soon as they attach a reason string or user properties.

All six now use readVariableByteInteger(), and each rejects a length too
short to hold the fields the specification requires.

PUBREL also accepted a length of exactly 2 even for MQTT 5.0, which
rejected valid PUBREL packets carrying a reason code. It now accepts 2
or more there, and still requires exactly 2 for MQTT 3.1.1.

- Adds three regression tests driving the parser through the existing
FakeServer, so they need no broker.

Pick-to: 6.11 6.12 6.8
Task-number: QTBUG-149569
Change-Id: Ib239d836556e0cc14e13c116dee757fdd1a7ae81
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-09-01 17:40:37 +00:00
..
auto Read the Remaining Length as a variable byte integer everywhere 2026-09-01 17:40:37 +00:00
benchmarks Add tests for websocket support for mqtt 2025-01-29 15:54:55 +01:00
certificate Add tests for websocket support for mqtt 2025-01-29 15:54:55 +01:00
common Implement waitForBytesWritten for the websockets case 2025-09-10 11:39:48 +02:00
libfuzzer/mqtt/data_receive Change license for test files 2024-03-20 08:11:56 +01:00
manual Only call find_package when building tests as standalone 2024-11-28 18:02:17 +01:00
CMakeLists.txt Band-aid patch for overriding mosquitto installation detection 2025-04-11 08:01:20 +00:00
README.txt Add README for using auto tests 2018-02-02 07:59:27 +00:00

The tests included in the subdirectories check for functionality and
conformance of the Qt MQTT module.

To be able to run the tests successfully, a broker needs to be available and
reachable.

The continuous integration utilized the paho conformance test broker. It can
be obtained at this location:
https://github.com/eclipse/paho.mqtt.testing

For the unit tests being able to locate this script, use the
MQTT_TEST_BROKER_LOCATION environment variable and set it
to “<install-path>/interoperability/startbroker.py”.

Alternatively, any broker can be instantiated and passed to the auto tests
by using the environment variable MQTT_TEST_BROKER. This must point to a
valid url. The broker must run on the standardized port 1883.

Note, that the unit tests verify functionality against the MQTT 3.1.1 version
of the standard, hence the broker needs to be compliant to the adherent
specifications.