fix: fix signed integer overflow in remaining length decoding

The expression (buffer[i] & 0x7f) << (7 * (i - 1)) performs a left
shift on a signed int. When i >= 5, the shift amount reaches 28+ and
0x7f << 28 overflows INT_MAX, which is undefined behavior.

Per MQTT 3.1.1 section 2.2.3, the Remaining Length field uses at most
4 continuation bytes, so limit the decoding loop accordingly. Also
cast to size_t in mqtt_get_total_length() where totlen is already
size_t.

Affects mqtt_get_total_length() and mqtt_get_publish_data().

Found via coverage-guided fuzzing (libFuzzer + UBSan).
This commit is contained in:
Eun0us
2026-06-18 15:02:44 +02:00
committed by Euripedes Rocha Filho
parent 0176939742
commit 02e02f1f6e
+4 -3
View File
@@ -143,8 +143,9 @@ size_t mqtt_get_total_length(const uint8_t *buffer, size_t length, int *fixed_si
int i;
size_t totlen = 0;
for (i = 1; i < length; ++i) {
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
for (i = 1; i < length && i <= 4; ++i) {
totlen += (size_t)(buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0) {
++i;
break;
@@ -223,7 +224,7 @@ char *mqtt_get_publish_data(uint8_t *buffer, size_t *length)
int blength = *length;
*length = 0;
for (i = 1; i < blength; ++i) {
for (i = 1; i < blength && i <= 4; ++i) {
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0) {
++i;