Skip to content

Commit 3b4e336

Browse files
committed
fix(packetlen): read + calculate variable packet length
1 parent 86669fd commit 3b4e336

File tree

1 file changed

+14
-94
lines changed

1 file changed

+14
-94
lines changed

Adafruit_MQTT.cpp

Lines changed: 14 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -562,111 +562,31 @@ 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-
Serial.print("Remaining len (len -4 header bytes): ");
568-
uint16_t remainingLen = len - 4; // subtract the 4 header bytes
569-
Serial.println(remainingLen);
570-
uint16_t topicoffset = packetAdditionalLen(remainingLen);
571-
Serial.print("Topic offset (packetAdditionalLen): ");
572-
Serial.println(topicoffset);
573-
uint16_t topicstart = topicoffset + 4;
574-
Serial.print("Topic start (offset + 4): ");
575-
Serial.println(topicstart);
576-
577-
578-
Serial.print("buf[2 + topicoffset]: '");
579-
Serial.print(buffer[2 + topicoffset]);
580-
Serial.print("' (");
581-
Serial.print(buffer[2 + topicoffset], HEX);
582-
Serial.println(")");
583-
uint16_t msb = buffer[2 + topicoffset] << 8;
584-
Serial.print("MSB (buf[2 + topicoffset] << 8): ");
585-
Serial.println(msb);
586-
uint16_t lsb = buffer[3 + topicoffset];
587-
Serial.print("LSB (buf[3 + topicoffset]): ");
588-
Serial.print(lsb);
589-
Serial.print(" ('");
590-
Serial.print(buffer[3 + topicoffset]);
591-
Serial.print("' = 0x");
592-
Serial.print(buffer[3 + topicoffset], HEX);
593-
Serial.println(")");
594-
uint16_t topiclen_sb = int(msb | lsb);
595-
Serial.print("Topic length (msb | lsb): ");
596-
Serial.println(topiclen_sb);
597-
598-
topiclen = int((buffer[2 + topicoffset]) << 8 | buffer[3 + topicoffset]);
599-
DEBUG_PRINT(F("Looking for subscription len "));
600-
DEBUG_PRINTLN(topiclen);
601-
602-
603-
// NEW WORKING CODE:
604-
605-
// Parse variable length encoding
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 flag.
568+
// This loop advances 'offset' to the first byte after the remaining length field.
606569
uint32_t multiplier = 1;
607-
DEBUG_PRINT("new technique - multiplier: 1");
608570
uint32_t value = 0;
609571
uint8_t encodedByte;
610-
uint8_t offset = 1; // start after first header byte
572+
uint8_t offset = 1; // Start after the fixed header byte
611573
do {
612574
encodedByte = buffer[offset++];
613575
value += (encodedByte & 127) * multiplier;
614576
multiplier *= 128;
577+
// Infinite loop protection: MQTT spec allows max 4 bytes for this field
578+
if (offset > 5) { // 1 (header) + 4 (max length bytes)
579+
DEBUG_PRINTLN(F("Bad MQTT packet: Remaining Length field too long / malformed"));
580+
return NULL;
581+
}
615582
} while ((encodedByte & 128) != 0);
616-
DEBUG_PRINT(F("new technique - value: "));
617-
DEBUG_PRINTLN(value);
618-
DEBUG_PRINT(F("new technique - offset: "));
619-
DEBUG_PRINTLN(offset);
620583

621-
// Now offset points to the first byte of topic length
584+
// Now 'offset' points to the first byte of the topic length field.
585+
// The topic length is always 2 bytes, big-endian.
622586
uint16_t new_msb = buffer[offset] << 8;
623-
DEBUG_PRINT(F("new technique - new_msb: "));
624-
DEBUG_PRINTLN(new_msb);
625587
uint16_t new_lsb = buffer[offset + 1];
626-
DEBUG_PRINT(F("new technique - new_lsb: "));
627-
DEBUG_PRINTLN(new_lsb);
628-
uint16_t new_topiclen = new_msb | new_lsb;
629-
DEBUG_PRINT(F("new technique - new_topiclen: "));
630-
DEBUG_PRINTLN(new_topiclen);
631-
uint16_t new_topicstart = offset + 2;
632-
DEBUG_PRINT(F("new technique - new_topicstart: "));
633-
DEBUG_PRINTLN(new_topicstart);
634-
635-
DEBUG_PRINT(F("Old topic offset (2 less) vs new topic offset: "));
636-
DEBUG_PRINT(topicoffset);
637-
DEBUG_PRINT(F(" vs "));
638-
DEBUG_PRINTLN(new_topicstart);
639-
640-
DEBUG_PRINT(F("Old topic start vs new topic start: "));
641-
DEBUG_PRINT(topicstart);
642-
DEBUG_PRINT(F(" vs "));
643-
DEBUG_PRINTLN(new_topicstart);
644-
645-
DEBUG_PRINT(F("Old topic len vs new topic len: "));
646-
DEBUG_PRINT(topiclen);
647-
DEBUG_PRINT(F(" vs "));
648-
DEBUG_PRINTLN(new_topiclen);
649-
650-
topiclen = new_topiclen;
651-
topicstart = new_topicstart;
652-
/*
653-
// Parse MQTT Remaining Length field (variable length encoding)
654-
uint8_t headerLen = 1;
655-
uint32_t remainingLen = 0;
656-
uint8_t multiplier = 1;
657-
uint8_t encodedByte;
658-
do {
659-
encodedByte = buffer[headerLen++];
660-
remainingLen += (encodedByte & 127) * multiplier;
661-
multiplier *= 128;
662-
} while ((encodedByte & 128) != 0);
663-
664-
// Now headerLen is the offset to the variable header
665-
uint16_t topiclen = (buffer[headerLen] << 8) | buffer[headerLen + 1];
666-
const char* topic = (const char*)&buffer[headerLen + 2];
667-
const uint8_t* payload = (const uint8_t*)&buffer[headerLen + 2 + topiclen];
668-
// payload length = remainingLen - (2 + topiclen [+2 for packet id if QoS > 0])
669-
*/
588+
uint16_t topiclen = new_msb | new_lsb;
589+
uint16_t topicstart = offset + 2;
670590

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

0 commit comments

Comments
 (0)