Skip to content

Defer HTTP parser callback errors #256

Description

@bettercallsaulj

Defer HTTP parser callback errors

Issue

HTTP parser callbacks could report errors synchronously while llhttp was still executing inside HttpCodecFilter::dispatch().

That is unsafe because the error path can disconnect MCP state, close transports, and destroy filter-owned objects while the parser callback stack is still unwinding. In practice, malformed or oversized body callbacks could trigger teardown from inside the parser itself, creating a use-after-free or crash risk on the transport read path.

How to reproduce

  1. Build the SDK with HTTP transport enabled.
  2. Create an HTTP client or server path using HttpCodecFilter.
  3. Feed an HTTP message that causes a parser callback error while dispatch() is processing input. One practical trigger is an invalid body callback condition from the oversized-body guard path:
body callback data = null and length > 0

or

body callback length > codec body chunk limit
  1. Make the registered message error callback close the MCP connection or transport.

Before the fix, the parser callback could call the error path immediately. That allowed connection shutdown and object destruction to run before llhttp_execute() and HttpCodecFilter::dispatch() finished unwinding.

Expected fixed behavior

Parser callback errors are stored in pending_parser_error_ instead of reported directly from the callback.

After parser execution returns and the input buffer is drained, dispatch() checks pending_parser_error_, clears it, and then calls the parser error handling path. This keeps parser callbacks from tearing down the connection while the parser is still active on the stack.

Regression check

A regression test should trigger a parser callback failure and assert that:

  1. the callback returns parser error;
  2. the user-facing error callback is not invoked synchronously from inside the parser body callback;
  3. the error is reported after dispatch() regains control;
  4. connection teardown from the error callback does not destroy objects still active in the parser callback stack.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions