Skip to content

Robustness Improvements#91

Open
MarcAntoineCRUE wants to merge 15 commits intohmueller01:masterfrom
MarcAntoineCRUE:dev/performances
Open

Robustness Improvements#91
MarcAntoineCRUE wants to merge 15 commits intohmueller01:masterfrom
MarcAntoineCRUE:dev/performances

Conversation

@MarcAntoineCRUE
Copy link

Summary

This merge request significantly improves the robustness and safety of the PubSubClient library, without changing its public API or breaking existing usage. All changes are fully covered by the test suite (57/57 tests passing).

Key Fixes

  • Payload Length Underflow Protection: In handlePacket(), the calculation of payloadLen is now guarded to prevent unsigned underflow if a malformed packet claims a topic length larger than the actual buffer. This prevents potential buffer overreads and undefined behavior.
  • Payload Offset Overflow Protection: The calculation of payloadOffset now uses size_t instead of uint16_t to avoid silent overflow when handling large topics.
  • Consistent State in setBufferSize():
    The buffer size and pointer are only updated after a successful allocation. If allocation fails, the previous buffer and size remain unchanged, preventing inconsistent internal state.
  • Null Buffer Guards in connect() and disconnect(): Both methods now check for a valid buffer pointer before use, preventing possible null pointer dereference if buffer allocation failed at construction.
  • Type Safety in subscribeImpl() and unsubscribeImpl(): Internal length variables now use size_t instead of uint16_t to avoid narrowing/truncation when handling large topics.

Rationale

These changes address potential edge cases that could lead to:

  • Buffer overflows or underflows
  • Crashes due to null pointer dereference
  • Silent data corruption with large topics or payloads
  • Inconsistent internal state after memory allocation failures

All fixes are implemented with minimal code changes and maintain full backward compatibility.

Copy link
Owner

@hmueller01 hmueller01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A first glimps over the changes ... lots of good stuff, but still a few changes.

…ing buffer safety checks and memory management improvements
@MarcAntoineCRUE
Copy link
Author

@hmueller01 I think I finished the modification and ready for your final review if I'm right

@github-actions
Copy link

Memory usage change @ 2e44c48

Board flash % RAM for global variables %
arduino:avr:uno 🔺 +296 - +430 +0.92 - +1.33 0 - 0 0.0 - 0.0
arduino:megaavr:uno2018 🔺 +124 - +254 +0.25 - +0.52 0 - 0 0.0 - 0.0
arduino:samd:mkr1000 🔺 +72 - +72 +0.03 - +0.03 0 - 0 0.0 - 0.0
esp32:esp32:esp32 🔺 +52 - +60 0.0 - 0.0 0 - 0 0.0 - 0.0
esp8266:esp8266:generic N/A N/A N/A N/A
Click for full report table
Board examples/mqtt_auth
flash
% examples/mqtt_auth
RAM for global variables
% examples/mqtt_basic
flash
% examples/mqtt_basic
RAM for global variables
% examples/mqtt_progmem
flash
% examples/mqtt_progmem
RAM for global variables
% examples/mqtt_publish_in_callback
flash
% examples/mqtt_publish_in_callback
RAM for global variables
% examples/mqtt_reconnect_nonblocking
flash
% examples/mqtt_reconnect_nonblocking
RAM for global variables
% examples/mqtt_stream
flash
% examples/mqtt_stream
RAM for global variables
% examples/mqtt_esp
flash
% examples/mqtt_esp
RAM for global variables
% examples/mqtt_esp_large_message
flash
% examples/mqtt_esp_large_message
RAM for global variables
%
arduino:avr:uno 296 0.92 0 0.0 430 1.33 0 0.0 426 1.32 0 0.0 296 0.92 0 0.0 386 1.2 0 0.0 304 0.94 0 0.0
arduino:megaavr:uno2018 130 0.27 0 0.0 124 0.25 0 0.0 254 0.52 0 0.0 130 0.27 0 0.0 128 0.26 0 0.0 130 0.27 0 0.0
arduino:samd:mkr1000 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0
esp32:esp32:esp32 52 0.0 0 0.0 52 0.0 0 0.0 52 0.0 0 0.0 52 0.0 0 0.0 52 0.0 0 0.0 56 0.0 0 0.0 60 0.0 0 0.0
esp8266:esp8266:generic N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
Click for full report CSV
Board,examples/mqtt_auth<br>flash,%,examples/mqtt_auth<br>RAM for global variables,%,examples/mqtt_basic<br>flash,%,examples/mqtt_basic<br>RAM for global variables,%,examples/mqtt_progmem<br>flash,%,examples/mqtt_progmem<br>RAM for global variables,%,examples/mqtt_publish_in_callback<br>flash,%,examples/mqtt_publish_in_callback<br>RAM for global variables,%,examples/mqtt_reconnect_nonblocking<br>flash,%,examples/mqtt_reconnect_nonblocking<br>RAM for global variables,%,examples/mqtt_stream<br>flash,%,examples/mqtt_stream<br>RAM for global variables,%,examples/mqtt_esp<br>flash,%,examples/mqtt_esp<br>RAM for global variables,%,examples/mqtt_esp_large_message<br>flash,%,examples/mqtt_esp_large_message<br>RAM for global variables,%
arduino:avr:uno,296,0.92,0,0.0,430,1.33,0,0.0,426,1.32,0,0.0,296,0.92,0,0.0,386,1.2,0,0.0,304,0.94,0,0.0
arduino:megaavr:uno2018,130,0.27,0,0.0,124,0.25,0,0.0,254,0.52,0,0.0,130,0.27,0,0.0,128,0.26,0,0.0,130,0.27,0,0.0
arduino:samd:mkr1000,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0
esp32:esp32:esp32,52,0.0,0,0.0,52,0.0,0,0.0,52,0.0,0,0.0,52,0.0,0,0.0,52,0.0,0,0.0,,,,,56,0.0,0,0.0,60,0.0,0,0.0
esp8266:esp8266:generic,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A

Copy link
Owner

@hmueller01 hmueller01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I proposed a solution, could you check if it is ok for you?

The change looks good for me!

@github-actions
Copy link

Memory usage change @ 433923c

Board flash % RAM for global variables %
arduino:avr:uno 🔺 +336 - +534 +1.04 - +1.66 0 - 0 0.0 - 0.0
arduino:megaavr:uno2018 🔺 +164 - +362 +0.34 - +0.74 0 - 0 0.0 - 0.0
arduino:samd:mkr1000 🔺 +96 - +96 +0.04 - +0.04 0 - 0 0.0 - 0.0
esp32:esp32:esp32 🔺 +80 - +92 +0.01 - +0.01 0 - 0 0.0 - 0.0
esp8266:esp8266:generic N/A N/A N/A N/A
Click for full report table
Board examples/mqtt_auth
flash
% examples/mqtt_auth
RAM for global variables
% examples/mqtt_basic
flash
% examples/mqtt_basic
RAM for global variables
% examples/mqtt_progmem
flash
% examples/mqtt_progmem
RAM for global variables
% examples/mqtt_publish_in_callback
flash
% examples/mqtt_publish_in_callback
RAM for global variables
% examples/mqtt_reconnect_nonblocking
flash
% examples/mqtt_reconnect_nonblocking
RAM for global variables
% examples/mqtt_stream
flash
% examples/mqtt_stream
RAM for global variables
% examples/mqtt_esp
flash
% examples/mqtt_esp
RAM for global variables
% examples/mqtt_esp_large_message
flash
% examples/mqtt_esp_large_message
RAM for global variables
%
arduino:avr:uno 336 1.04 0 0.0 470 1.46 0 0.0 534 1.66 0 0.0 336 1.04 0 0.0 426 1.32 0 0.0 344 1.07 0 0.0
arduino:megaavr:uno2018 170 0.35 0 0.0 164 0.34 0 0.0 362 0.74 0 0.0 170 0.35 0 0.0 168 0.35 0 0.0 170 0.35 0 0.0
arduino:samd:mkr1000 96 0.04 0 0.0 96 0.04 0 0.0 96 0.04 0 0.0 96 0.04 0 0.0 96 0.04 0 0.0 96 0.04 0 0.0
esp32:esp32:esp32 80 0.01 0 0.0 80 0.01 0 0.0 80 0.01 0 0.0 80 0.01 0 0.0 80 0.01 0 0.0 84 0.01 0 0.0 92 0.01 0 0.0
esp8266:esp8266:generic N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
Click for full report CSV
Board,examples/mqtt_auth<br>flash,%,examples/mqtt_auth<br>RAM for global variables,%,examples/mqtt_basic<br>flash,%,examples/mqtt_basic<br>RAM for global variables,%,examples/mqtt_progmem<br>flash,%,examples/mqtt_progmem<br>RAM for global variables,%,examples/mqtt_publish_in_callback<br>flash,%,examples/mqtt_publish_in_callback<br>RAM for global variables,%,examples/mqtt_reconnect_nonblocking<br>flash,%,examples/mqtt_reconnect_nonblocking<br>RAM for global variables,%,examples/mqtt_stream<br>flash,%,examples/mqtt_stream<br>RAM for global variables,%,examples/mqtt_esp<br>flash,%,examples/mqtt_esp<br>RAM for global variables,%,examples/mqtt_esp_large_message<br>flash,%,examples/mqtt_esp_large_message<br>RAM for global variables,%
arduino:avr:uno,336,1.04,0,0.0,470,1.46,0,0.0,534,1.66,0,0.0,336,1.04,0,0.0,426,1.32,0,0.0,344,1.07,0,0.0
arduino:megaavr:uno2018,170,0.35,0,0.0,164,0.34,0,0.0,362,0.74,0,0.0,170,0.35,0,0.0,168,0.35,0,0.0,170,0.35,0,0.0
arduino:samd:mkr1000,96,0.04,0,0.0,96,0.04,0,0.0,96,0.04,0,0.0,96,0.04,0,0.0,96,0.04,0,0.0,96,0.04,0,0.0
esp32:esp32:esp32,80,0.01,0,0.0,80,0.01,0,0.0,80,0.01,0,0.0,80,0.01,0,0.0,80,0.01,0,0.0,,,,,84,0.01,0,0.0,92,0.01,0,0.0
esp8266:esp8266:generic,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A

@hmueller01
Copy link
Owner

@MarcAntoineCRUE Somehow endPublish() fails now ...

@MarcAntoineCRUE
Copy link
Author

@MarcAntoineCRUE Somehow endPublish() fails now ...

Sorry for that mistake, I was not able to work on this issue last week, I think it shall be correct now

@hmueller01
Copy link
Owner

Thanks for the update! I havn't found time to look into it as well. Will test the PR on a real device the next days.
@TD-er What do you think about the (little bit to big) change of this PR?

@github-actions
Copy link

github-actions bot commented Mar 9, 2026

Memory usage change @ 8d039a5

Board flash % RAM for global variables %
arduino:avr:uno 🔺 +294 - +428 +0.91 - +1.33 0 - 0 0.0 - 0.0
arduino:megaavr:uno2018 🔺 +122 - +256 +0.25 - +0.53 0 - 0 0.0 - 0.0
arduino:samd:mkr1000 🔺 +72 - +72 +0.03 - +0.03 0 - 0 0.0 - 0.0
esp32:esp32:esp32 🔺 +48 - +56 0.0 - 0.0 0 - 0 0.0 - 0.0
esp8266:esp8266:generic N/A N/A N/A N/A
Click for full report table
Board examples/mqtt_auth
flash
% examples/mqtt_auth
RAM for global variables
% examples/mqtt_basic
flash
% examples/mqtt_basic
RAM for global variables
% examples/mqtt_progmem
flash
% examples/mqtt_progmem
RAM for global variables
% examples/mqtt_publish_in_callback
flash
% examples/mqtt_publish_in_callback
RAM for global variables
% examples/mqtt_reconnect_nonblocking
flash
% examples/mqtt_reconnect_nonblocking
RAM for global variables
% examples/mqtt_stream
flash
% examples/mqtt_stream
RAM for global variables
% examples/mqtt_esp
flash
% examples/mqtt_esp
RAM for global variables
% examples/mqtt_esp_large_message
flash
% examples/mqtt_esp_large_message
RAM for global variables
%
arduino:avr:uno 294 0.91 0 0.0 428 1.33 0 0.0 428 1.33 0 0.0 294 0.91 0 0.0 384 1.19 0 0.0 302 0.94 0 0.0
arduino:megaavr:uno2018 128 0.26 0 0.0 122 0.25 0 0.0 256 0.53 0 0.0 128 0.26 0 0.0 126 0.26 0 0.0 128 0.26 0 0.0
arduino:samd:mkr1000 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0 72 0.03 0 0.0
esp32:esp32:esp32 48 0.0 0 0.0 48 0.0 0 0.0 48 0.0 0 0.0 48 0.0 0 0.0 48 0.0 0 0.0 52 0.0 0 0.0 56 0.0 0 0.0
esp8266:esp8266:generic N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A N/A
Click for full report CSV
Board,examples/mqtt_auth<br>flash,%,examples/mqtt_auth<br>RAM for global variables,%,examples/mqtt_basic<br>flash,%,examples/mqtt_basic<br>RAM for global variables,%,examples/mqtt_progmem<br>flash,%,examples/mqtt_progmem<br>RAM for global variables,%,examples/mqtt_publish_in_callback<br>flash,%,examples/mqtt_publish_in_callback<br>RAM for global variables,%,examples/mqtt_reconnect_nonblocking<br>flash,%,examples/mqtt_reconnect_nonblocking<br>RAM for global variables,%,examples/mqtt_stream<br>flash,%,examples/mqtt_stream<br>RAM for global variables,%,examples/mqtt_esp<br>flash,%,examples/mqtt_esp<br>RAM for global variables,%,examples/mqtt_esp_large_message<br>flash,%,examples/mqtt_esp_large_message<br>RAM for global variables,%
arduino:avr:uno,294,0.91,0,0.0,428,1.33,0,0.0,428,1.33,0,0.0,294,0.91,0,0.0,384,1.19,0,0.0,302,0.94,0,0.0
arduino:megaavr:uno2018,128,0.26,0,0.0,122,0.25,0,0.0,256,0.53,0,0.0,128,0.26,0,0.0,126,0.26,0,0.0,128,0.26,0,0.0
arduino:samd:mkr1000,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0,72,0.03,0,0.0
esp32:esp32:esp32,48,0.0,0,0.0,48,0.0,0,0.0,48,0.0,0,0.0,48,0.0,0,0.0,48,0.0,0,0.0,,,,,52,0.0,0,0.0,56,0.0,0,0.0
esp8266:esp8266:generic,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A

Copy link
Owner

@hmueller01 hmueller01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on a real device. Looks good.

@hmueller01
Copy link
Owner

@TD-er Do you approve the changes as well?

@TD-er
Copy link
Collaborator

TD-er commented Mar 15, 2026

@TD-er Do you approve the changes as well?

I will have a look tomorrow as I have not been near a PC in the last few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants