-
Notifications
You must be signed in to change notification settings - Fork 293
Adafruit_MQTT::publishPacket: Protect against memory corruption. #166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ba0f9df
to
2847f9f
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
2847f9f
to
6389dc4
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
6389dc4
to
9aedbd9
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
9aedbd9
to
4204e1d
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
4204e1d
to
6bcc819
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
6bcc819
to
ad914cd
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
ad914cd
to
3fdbdfb
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
3fdbdfb
to
785b5a4
Compare
It's 2021 and I still struggled to find that this is the reason why my program is crashing. Please review this PR asap for the sake of our mental health. |
I share the frustration :( There seems to be a lot of nice PRs that have been sitting for more than a year. It's a shame. Thankfully platformIO lets me use git repos for lib_deps, so I forked your fix @flavio-fernandes, and used that. Thanks for the work you put in! :) I'd switch to something like Async MQTT, but I need to use a library that uses a Client object like this, to work with my bearSSL certificate store. |
Maybe @ladyada or @brentru can listen to our cries. I do not mind if a different PR gets used; just wish for a better experience using this awesome library. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@flavio-fernandes Made two small comments. Rest looks good and is similar to a portion of MiniMQTT which I've implemented to address a similar issue.
After you're done addressing them, please bump the patch version
number in https://github.com/adafruit/Adafruit_MQTT_Library/blob/master/library.properties#L2 by 1 so we can get this picked up by the Arduino Library Manager tool.
Adafruit_MQTT.h
Outdated
uint16_t publishPacket(uint8_t *packet, const char *topic, uint8_t *payload, | ||
uint16_t bLen, uint8_t qos); | ||
uint16_t bLen, uint8_t qos, uint16_t maxPacketLen); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@flavio-fernandes is there a way to protect against memory corruption without changing the function signature here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really. 😄 I think that the only way we can protect from the memory corruption is by knowing how much space is available to begin with.
This is a private member function, so there should not be a concern about changing its signature, agree?
Regardless, I made the extra parameter have the default value of 0, so caller will still work should we try to use the old function arguments.
Adafruit_MQTT.cpp
Outdated
@@ -665,11 +666,22 @@ uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) { | |||
return len; | |||
} | |||
|
|||
uint16_t Adafruit_MQTT::packetAdditionalLen(uint16_t currLen) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this instead be incorporated into publishPacket
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I will use that function in cpp file as a static. So this new line is now removed.
Ack! TBH, it has been a while since I thought about this PR. |
@flavio-fernandes ok, let me know when its ready to review. I have a pretty large MQTT application which uses this library and I'd like to test with that. |
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
785b5a4
to
08c6ded
Compare
Avoid memory corruption from happening when data payload provided in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE. In order to do that, a helper function is being added to calculate how much space is available for the payload after subtracting what is used as the header. Pull request adafruit#166 Fixes adafruit#109 Fixes adafruit#122 Signed-off-by: Flavio Fernandes <[email protected]>
7565b2e
to
3074f51
Compare
Hi @brentru ! Okay, I made the changes and pushed an update. Let me know what you think, please. Best! |
@flavio-fernandes Could you bump to 2.2.0? I tested this against a SECRET project and it prevents corruption there as well. |
3074f51
to
fff701e
Compare
@brentru : Done bumping to 2.2.0 . Secret project? You make me curious! :) |
return 0; | ||
if (currLen < 16384) | ||
return 1; | ||
if (currLen < 2097151) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think currLen (unsigned 16-bit) will always be less than 65536, so this comparison might give an unexpected result (I made the same mistake, still trying to think of a solution. I've noticed that many types in this class assume maximum lengths that might not be compatible with all message/packet lengths -- some discussion might be helpful there).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right! I still think that the compare should work, granted the compiler promote the type. If not, we could explicitly cast the variable to uitn32u, but that may not be doable on older arduino boards?
Fixes #109
Fixes #122
After spending a long time pulling my hair to understand why I was
hitting a panic when attempting to read from my registered
subscriptions, I found out that the subscriptions member of the
Adafruit_MQTT instance was corrupted. :(
Turns out the memory corruption was caused by my publish
call, where the payload I was providing was bigger than the
allocated space in the buffer for construction of the packet
(see buffer[MAXBUFFERSIZE]).
To protect myself from ever making this mistake again, I am
proposing a simple logic in publishPacket where instead of
silently corrupting memory, the code uses as much payload
as it can fit in the available space. By seeing the
truncated payload, user can decide whether he/she should
1)break it up into different topics, 2) put the payload on
a diet, or 3) increase MAXBUFFERSIZE.
====
of the code were modified. This will help us understand any risks of integrating
the code.
This pull requests improves the handling of buffer for packet creation of
Adafruit_MQTT::publishPacket. It adds argument maxPacketLen to keep track
of how much space is available in buffer.
doesn't apply to a supported platform of the library please mention it.
This change is not modifying the sizes of any buffers. Instead, it truncates
the payload to avoid memory corruption of the class Adafruit_MQTT by keeping
packet creation from going beyond MAXBUFFERSIZE.
strive to not break users of the code and running tests/examples helps with this
process.
See this gist with an example code where a packet has a payload that exceeds
MAXBUFFERSIZE and corrupts packet_id_counter and subscriptions of the
Adafruit_MQTT instance.
See comments below that gist with the crash and stack trace of code above, where memory is
corrupted and the LoadProhibited exception takes place.
Lastly, see the comment that follows with the proposed modification, where the same code
simply gets the payload truncated instead of allowing memory to get messed up.