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.
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();
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.