Skip to content

[BUG] uri_log crashes with std::logic_error when MHD passes null URI under high load #371

@judith-ipac

Description

@judith-ipac

Thanks to Claude for debugging and for writing this description.

Under high load, libmicrohttpd can invoke MHD_OPTION_URI_LOG_CALLBACK with a null uri pointer — for example when a TCP connection is accepted but the client disconnects or sends non-HTTP data before the request line is parsed. In this situation, uri_log() in src/webserver.cpp passes the null pointer directly to std::string's constructor, which throws std::logic_error("basic_string::_M_construct null not valid"). Because this exception is thrown in a MHD callback with no enclosing catch, std::terminate() is called and the process aborts.
Steps to reproduce
Under high load, cause a TCP connection to be accepted by the MHD daemon without a valid HTTP request line being delivered — for example via a port scanner, a TLS client hitting a plain HTTP port, or connection exhaustion causing half-open connections.

Expected behavior
The server handles the null URI gracefully, treating it as an empty or unknown URI rather than crashing.
Actual behavior
std::terminate() is called, killing the process. The stack trace is:
#10 __cxa_throw () from libstdc++.so.6
#11 std::__throw_logic_error(char const*) () from libstdc++.so.6
#12 httpserver::uri_log(void*, char const*, MHD_Connection*) () from libhttpserver.so.0
#13 (libmicrohttpd internal)
Disassembly of uri_log confirms the exception message is "basic_string::_M_construct null not valid", thrown at:

mr->complete_uri = std::make_unique(uri); // src/webserver.cpp line 423

Environment

libhttpserver 0.19.0
libmicrohttpd 0.9.72 (Debian 11 package libmicrohttpd-dev:amd64 0.9.72-2+deb11u1)
GCC 10.2.1
Linux x86_64

Suggested fix

diff--- a/src/webserver.cpp
+++ b/src/webserver.cpp
@@ -1,6 +1,7 @@
void* uri_log(void* cls, const char* uri, struct MHD_Connection *con) {
std::ignore = cls;
std::ignore = con;
auto mr = std::make_uniquedetails::modded_request();

  • mr->complete_uri = std::make_unique(uri);
  • mr->complete_uri = std::make_unique(uri != nullptr ? uri : "");
    return reinterpret_cast<void*>(mr.release());

This is consistent with MHD's documented behaviour that the URI log callback may be invoked before the connection is fully initialized. An empty string URI will simply fail to match any registered resource and result in a 404, which is the correct graceful behaviour.

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