Skip to content

Vulnerability Report: Content-Length Signed Integer Overflow #77

@Ch1ps-dot

Description

@Ch1ps-dot

Summary

The HTTP request parser accumulates the Content-Length header into a signedint64_t without checking for overflow. An attacker can send an oversized decimal Content-Length value such as 18446744073709551615 and cause the internal content_length field to wrap to a negative value.

After the overflow, the parser may emit a body token with a negative len field. Applications that trust this token length, especially code that casts it to size_t, copies it, allocates from it, or forwards it into other APIs, can hit denial of service or memory safety failures.

Affected Code

  • src/parser.rl: content_length_digit
  • src/parser.rl: done_headers
  • src/parser.rl: small_body_read

The vulnerable accumulation happens here:

parser->content_length *= 10;
parser->content_length += fc - '0';

No bounds check is performed before multiplying or adding.

Impact

Potential impacts include:

  • Request parser state corruption through signed integer overflow.
  • Negative body token lengths exposed to application handlers.
  • Denial of service if downstream code allocates, copies, or validates based on
    the corrupted length.
  • Possible memory safety issues in applications that convert the negative
    signed length to an unsigned size.

The exact exploitability depends on how the embedding application handles
http_request_body() or streamed body chunks.

Root Cause

The parser treats Content-Length as an unbounded decimal integer and updates a
signed integer incrementally. Once the value exceeds INT64_MAX, the multiply
or add operation overflows. Signed integer overflow is undefined behavior in C.

The later body handling logic assumes parser->content_length is valid and
non-negative:

} else if (parser->content_length == 0) {
  ...
} else if (parser->content_length > max_buf_capacity - buffer->after_headers_index) {
  ...
} else {
  ...
  parser->token.len = parser->content_length;
}

When content_length has wrapped to -1, it bypasses the large-body path and
is eventually copied into token.len.

Recommended Fix

Reject Content-Length values that cannot be represented safely before
performing multiplication or addition. For example:

if (parser->content_length > (INT64_MAX - digit) / 10) {
  /* mark parser error and stop parsing */
}
parser->content_length = parser->content_length * 10 + digit;

Additional hardening recommendations:

  • Reject negative or overflowed body lengths before selecting small-body or
    streamed-body handling.
  • Enforce a maximum accepted Content-Length consistent with
    HTTP_MAX_REQUEST_BUF_SIZE.
  • Add unit tests for boundary values:
    • 9223372036854775807
    • 9223372036854775808
    • 18446744073709551615
    • long digit strings larger than 64 bits

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions