Skip to content

Commit 10c5d51

Browse files
authored
Merge pull request #233 from adafruit/packet-len-calc
handleSubscriptionPacket - topic calc error
2 parents 0a19fd0 + a38e837 commit 10c5d51

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

Adafruit_MQTT.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -562,15 +562,33 @@ Adafruit_MQTT_Subscribe *Adafruit_MQTT::handleSubscriptionPacket(uint16_t len) {
562562
return NULL;
563563
}
564564

565-
// Parse out length of packet.
566-
// NOTE: This includes data in the variable header and the payload.
567-
uint16_t remainingLen = len - 4; // subtract the 4 header bytes
568-
uint16_t const topicoffset = packetAdditionalLen(remainingLen);
569-
uint16_t const topicstart = topicoffset + 4;
570-
571-
topiclen = int((buffer[2 + topicoffset]) << 8 | buffer[3 + topicoffset]);
572-
DEBUG_PRINT(F("Looking for subscription len "));
573-
DEBUG_PRINTLN(topiclen);
565+
// Parse MQTT Remaining Length field (variable length encoding).
566+
// This field can be 1-4 bytes, so we must parse it byte-by-byte.
567+
// Each byte uses the lower 7 bits for data, and the MSB as a continuation
568+
// flag. This loop advances 'offset' to the first byte after the remaining
569+
// length field.
570+
uint32_t multiplier = 1;
571+
uint32_t value = 0;
572+
uint8_t encodedByte;
573+
uint8_t offset = 1; // Start after the fixed header byte
574+
do {
575+
encodedByte = buffer[offset++];
576+
value += (encodedByte & 127) * multiplier;
577+
multiplier *= 128;
578+
// Infinite loop protection: MQTT spec allows max 4 bytes for this field
579+
if (offset > 5) { // 1 (header) + 4 (max length bytes)
580+
DEBUG_PRINTLN(
581+
F("Bad MQTT packet: Remaining Length field too long / malformed"));
582+
return NULL;
583+
}
584+
} while ((encodedByte & 128) != 0);
585+
586+
// Now 'offset' points to the first byte of the topic length field.
587+
// The topic length is always 2 bytes, big-endian.
588+
uint16_t new_msb = buffer[offset] << 8;
589+
uint16_t new_lsb = buffer[offset + 1];
590+
topiclen = new_msb | new_lsb;
591+
uint16_t topicstart = offset + 2;
574592

575593
// Find subscription associated with this packet.
576594
for (i = 0; i < MAXSUBSCRIPTIONS; i++) {

0 commit comments

Comments
 (0)