@@ -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