Skip to content

Conversation

@AnaLGiN83
Copy link

Summary

This patch fixes a heap-use-after-free in Connection::handleWriteResponse() that occurs when handling HTTP keep-alive connections, particularly when the client disconnects or times out after sending a request.

In src/http/Connection.C, after sending an HTTP response on a keep-alive connection, the code removes all receive buffers except the last one:

while (rcv_buffers_.size() > 1)
  rcv_buffers_.pop_front();

if (rcv_remaining_ < rcv_buffers_.back().data() + rcv_buffer_size_)
  handleReadRequest0();

The bug: The pointer rcv_remaining_ may still point to data in a deleted buffer. The original condition only checks if rcv_remaining_ is less than the buffer end, but does not verify that it points within the bounds of the remaining buffer (i.e., >= buffer_start).

Trigger Scenario

This issue can be reliably reproduced when:

  1. Client sends an HTTP request
  2. Server processes it and starts sending response
  3. Client closes connection
  4. handleWriteResponse() is called to clean up for next keep-alive request
  5. rcv_remaining_ points to a deleted buffer → heap-use-after-free in RequestParser::consume()

ASAN Report

==8==ERROR: AddressSanitizer: heap-use-after-free on address 0x625000000306
READ of size 1 at 0x625000000306 thread T4
    #0 in http::server::RequestParser::consume() RequestParser.C:857
...

Full ASAN trace shows the memory was freed by pop_front() in the same thread just before the access.

Solution

Add a proper bounds check to verify that rcv_remaining_ points inside the remaining buffer.

Testing

Tested with AFL++ fuzzing harness (raw TCP packets fuzzing) using AddressSanitizer:

  • Before: Consistent heap-use-after-free on specific inputs
  • After: No memory errors detected

Test case that triggered the bug:

POST /api/data HTTP/1.1
Host: localhost
Content-Type: application/json
Content-Length: 36

{"name": "fuzz", "value": "test"}

Note, that Content-Length exceeds the real body length (33), so server waits fot more data from. Instead, client closes socket after 500ms, what leads to triggering the bug.

This fixes a memory safety issue in Connection::handleWriteResponse()
that occurs when handling HTTP keep-alive connections.

The bug: After removing old receive buffers via pop_front(), the pointer
rcv_remaining_ could still point to data in a deleted buffer. The original
condition only checked if rcv_remaining_ was less than the buffer end,
but did not verify it was within the bounds of the remaining buffer.

The fix: Add proper bounds checking to ensure rcv_remaining_ points inside
the remaining buffer before dereferencing it in handleReadRequest0().

Discovered via AFL++ fuzzing with AddressSanitizer.
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.

1 participant