HexBrain

curl · Report #3484319

MQTT Protocol Violation & Integer Overflow in libcurl

Informativestatus
highseverity
14upvotes
1 Jan 2026disclosed

How it was found

Executive Summary

Vulnerability Type: CWE-190 Component: lib/mqtt.c
Function: mqtt_decode_len

Affected Architectures:

  • All architectures: Protocol non-compliance leading to stream desynchronization
  • 32-bit architectures: Deterministic integer overflow in length decoding

libcurl does not correctly enforce the MQTT v3.1.1 specification limit for the “Remaining Length” field when decoding incoming packets. This allows malformed MQTT packets to be parsed incorrectly, leading to protocol desynchronization and potential denial of service. On 32-bit systems, the decoding logic additionally allows a deterministic integer overflow.


Root Cause: Inconsistent Length Handling

The issue is caused by an inconsistency within lib/mqtt.c.
The encoder correctly enforces the MQTT specification limit, while the decoder does not.

Correct Behavior (Encoding)

In mqtt_encode_len, the implementation explicitly limits the Remaining Length field to four bytes, as required by the specification:

for(i = 0; (len > 0) && (i < 4); i++) {
  unsigned char encoded;
  encoded = len % 0x80;
  /* ... */
}

This ensures protocol compliance.

Incorrect Behavior (Decoding)

In contrast, mqtt_decode_len does not enforce the same limit:

for(i = 0; (i < buflen) && (encoded & 128); i++) {
  encoded = buf[i];
  len += (encoded & 127) * mult;
  mult *= 128;
}

The loop continues as long as the continuation bit is set and input is available, allowing more than four bytes to be consumed as part of the Remaining Length field.


Specification Violation

According to the MQTT v3.1.1 specification, Section 2.2.3 (Remaining Length):

“The number of bytes in the Remaining Length field MUST NOT exceed four bytes.”

By accepting and processing length fields longer than four bytes, libcurl violates the MQTT specification and enters an undefined protocol state.


Integer Overflow on 32-bit Systems

On 32-bit architectures, size_t is a 32-bit unsigned integer. The variable mult is repeatedly multiplied by 128 during decoding.

Example progression on a 32-bit system:

Iterationmult valueOperationResult
011 × 128128
1128128 × 12816,384
216,384× 1282,097,152
32,097,152× 128268,435,456
4268,435,456× 128Overflow → 0

After the overflow, mult becomes zero, and any further bytes consumed contribute nothing to the decoded length. This allows a large or malformed Remaining Length field to be partially “hidden” while still advancing the input pointer.


Impact

Impact

Protocol Desynchronization (All Architectures)

By consuming more than four bytes for the Remaining Length field, libcurl can become desynchronized from the MQTT stream. Bytes intended to be part of the payload or subsequent packets may instead be interpreted as length data, causing incorrect parsing of later packets.

Denial of Service

This desynchronization can result in malformed packet handling, unexpected connection termination, or repeated protocol errors such as CURLE_WEIRD_SERVER_REPLY.

No memory corruption or code execution is claimed.


Recommended Fix

The decoding logic should explicitly enforce the four-byte limit defined by the MQTT specification.

Example fix:

for(i = 0; (i < buflen) && (encoded & 128); i++) {
  if(i >= 4) {
    /* Malformed Remaining Length */
    return 0; /* or propagate an error to the caller */
  }
  encoded = buf[i];
  len += (encoded & 127) * mult;
  mult *= 128;
}

Optionally, the decoded length can also be checked against the implementation limit:

if(len > MAX_MQTT_MESSAGE_SIZE)
  return 0;

Verification Notes

The issue was verified through code inspection and logic simulation, confirming that mqtt_decode_len accepts more than four bytes for the Remaining Length field and allows arithmetic overflow on 32-bit systems. Runtime exploitation was not required to demonstrate the protocol violation.


Conclusion

This is a protocol parsing bug caused by missing enforcement of a mandatory MQTT specification limit. While it does not directly result in memory corruption, it allows malformed MQTT packets to desynchronize the client’s protocol state and cause denial of service. Aligning the decoder with the existing encoder logic resolves the issue cleanly.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original