[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]

*Subject*: **Erratum: Error in Remaining Length Decoding Algorithm MQTT 3.1.1 § 2.2.3**

*From*:**Ed Briggs <edbriggs@microsoft.com>***To*: "mqtt@lists.oasis-open.org" <mqtt@lists.oasis-open.org>*Date*: Tue, 4 Aug 2015 19:43:55 +0000

While testing MQTT, I discovered an error in the Standard that will cause implementations to fail upon reception of PUBLISH messages in which the combination of topic length, QoS level, and payload size result in
a fixed header remaining length > 2,097,151. What is the process to amend the specification to help developers of MQTT implementations to avoid this failure? (I reviewed the
Approved Errata
process, but am seeking more guidance for how the MQTT TC is managing errata.) The culprit is an incorrect loop termination check in the algorithm for decoding the remaining length field provided in § 2.2.3. It causes decoding to fail for all encoded values greater than 2,097,151. Consequently,
reception fails with valid PUBLISH messages for which 2,097,152 ≤ remaining length The algorithm can be corrected by moving the location of the loop termination check within the loop body as shown in the pseudo code below. Although the algorithm is contained
in a section labeled "non-normative comment", a correction to the Standard seems desirable because developers are likely to copy the algorithm verbatim.
This error affects implementations using the algorithm in the MQTT 3.1.1 Standard. Implementations using other algorithms, including the older algorithm contained in MQTT 3.1, will not encounter this problem. However, as
noted in MQTT-29 item 3, the MQTT 3.1 algorithm is susceptible to buffer overflow attacks and similar problems because it cannot detect malformed remaining length encoding. Session partners of affected implementations can be indirectly affected because they will not receive acknowledgements from affected systems when using durable sessions and QoS > 0 because the failure is unrecoverable
by retransmission.
This error does not appear in the MQTT 3.1 Standard, and seems to have been introduced in MQTT 3.1.1 WD08 or WD09, possibly in response to safety concerns raised in MQTT-29 (item 3).
Non-normative comments in § 2.2.3 presents the following algorithm for decoding the remaining length field. (line numbers and emphasis added) : 1 multiplier = 1 2 value = 0 3 4 do 5 encodedByte = 'next byte from stream' 6 value += (encodedByte AND 127) * multiplier 7 multiplier *= 128 8
if (multiplier > 128*128*128) << ? Fails 9 throw Error(Malformed Remaining Length) 10 while ((encodedByte AND 128) != 0) The range check (line 8) fails because 4 bytes are required to encode values greater than
2,097,151. In the fourth iteration of the do-while loop, the multiplier exceeds the limit of 128*128*128 causing the range check to fail.
To correct this error, it is only necessary to move the range check so that it precedes the multiplier update. The corrected algorithm appears below: 1 multiplier = 1 2 value = 0 3 4 do 5 encodedByte = 'next byte from stream' 6 value += (encodedByte AND 127) * multiplier 7 if (multiplier > 128*128*128)
8 throw Error(Malformed Remaining Length) 9 multiplier *= 128 <<- Now follows range check 10 while ((encodedByte AND 128) != 0) With this change, the algorithm correctly encodes all values from 0 to 268,435,455, and rejects encoded values greater than 268,435,455 as required by the Standard. [NB: Both the original and corrected version
contain an unnecessary multiplication (line 8 and 9) respectively on the last iteration of the loop.] Thank you, Ed Briggs Microsoft Corporation |

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]