Skip to content

Fix std::terminate when uri_log receives null uri (#371)#372

Merged
etr merged 5 commits intomasterfrom
fix/issue-371-uri-log-null-uri
Apr 8, 2026
Merged

Fix std::terminate when uri_log receives null uri (#371)#372
etr merged 5 commits intomasterfrom
fix/issue-371-uri-log-null-uri

Conversation

@etr
Copy link
Copy Markdown
Owner

@etr etr commented Apr 7, 2026

Summary

  • Guard uri_log() in src/webserver.cpp against a null uri pointer from libmicrohttpd, treating it as an empty string instead of letting std::string's assignment operator throw std::logic_error.
  • Add a ChangeLog entry under the in-progress 0.20.0 release notes.

Background

As reported in #371, libmicrohttpd can invoke MHD_OPTION_URI_LOG_CALLBACK with a null uri pointer before the request line has been parsed — e.g. when a TCP connection is accepted but the client disconnects, sends non-HTTP data, or a TLS client hits a plain HTTP port. The previous code assigned the raw pointer directly into mr->complete_uri (a std::string), which throws std::logic_error(\"basic_string::_M_construct null not valid\"). Because the throw originates inside an MHD C callback with no enclosing handler, std::terminate() was called and the process aborted under load.

The reporter's stack trace pointed at src/webserver.cpp line 423 in 0.19.0; the equivalent line on master is now mr->complete_uri = uri; (line 629), but the bug is identical — std::string::operator=(const char*) is undefined for a null pointer and libstdc++ throws.

Fix

mr->complete_uri = (uri \!= nullptr) ? uri : "";

An empty URI simply fails to match any registered resource and surfaces as a 404, which is the correct graceful behaviour and matches the suggestion in the issue.

Test plan

  • make succeeds with -Werror -Wall -Wextra -pedantic
  • make check — all 14 tests pass (basic, file_upload, http_utils, threaded, nodelay, string_utilities, http_endpoint, ban_system, ws_start_stop, authentication, deferred, http_resource, http_response, create_webserver)
  • CI green

Resolves #371.

libmicrohttpd may invoke MHD_OPTION_URI_LOG_CALLBACK with a null uri
pointer before the request line is parsed - for example on port scans,
TLS clients hitting a plain HTTP port, or half-open connections. The
previous code assigned the raw pointer directly into a std::string,
which throws std::logic_error("basic_string::_M_construct null not
valid"). Because the throw originates inside an MHD C callback with
no enclosing handler, std::terminate() was called and the process
aborted under load.

Treat a null uri as an empty string so the assignment is well-defined.
An empty URI fails to match any registered resource and surfaces as a
404, which is the correct graceful behaviour.

Resolves #371.
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 7, 2026

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 67.97%. Comparing base (6c115f3) to head (f9c0d4e).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/webserver.cpp 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #372   +/-   ##
=======================================
  Coverage   67.97%   67.97%           
=======================================
  Files          28       28           
  Lines        1636     1636           
  Branches      672      672           
=======================================
  Hits         1112     1112           
  Misses         64       64           
  Partials      460      460           
Files with missing lines Coverage Δ
src/webserver.cpp 56.33% <0.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6c115f3...f9c0d4e. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

etr added 3 commits April 7, 2026 11:01
The CodeQL workflow was still pulling libmicrohttpd-0.9.64 from S3,
which is below the project's stated minimum of 1.0.0 and is no longer
served by the bucket - the install step was failing with "gzip:
stdin: not in gzip format" because curl received a 243-byte error
response instead of the tarball. Bump to 1.0.3 from the same S3
location so CodeQL can build the project again.
Aligns release.yml and verify-build.yml with codeql-analysis.yml so all
workflows pull the same libmicrohttpd-1.0.3.tar.gz from S3. This also
brings CI in line with the project's documented minimum of >= 1.0.0
(0.9.77 was below that threshold). Cache keys include the new version
so existing 0.9.77 entries are not reused.
Adds test/unit/uri_log_test.cpp to lock in the fix for issue #371. The
test calls uri_log() directly (re-declaring the symbol since it has no
public header) and verifies three cases:

  - null uri does not throw and yields an empty complete_uri
  - valid uri is stored verbatim
  - empty uri is stored verbatim

The first case is the regression check: against the unfixed code,
running the test crashes the process (SIGSEGV from dereferencing the
null pointer inside std::string's assignment operator on libstdc++ 13;
on the older libstdc++ 10 from the bug report it threw std::logic_error
and aborted via std::terminate). With the fix in place, all three sub-
tests pass cleanly.

The new test target needs an explicit -lmicrohttpd in its link line
because it instantiates ~modded_request() directly, which references
MHD_destroy_post_processor; the default LDADD only pulls libmicrohttpd
in transitively via libhttpserver.la, and modern ld enforces
--no-copy-dt-needed-entries.
cpplint flags bare "httpserver.hpp" with build/include_subdir [4].
Match the convention used by every other test file in the repo and
prefix the include with "./" so cpplint considers the directory
explicit.
@etr etr merged commit a752404 into master Apr 8, 2026
43 of 44 checks passed
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.

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

1 participant