Commit 57bfb14
committed
TASK-073: retire v0.99 framing of unescaper_func, document architectural rationale
The MHD_OPTION_UNESCAPE_CALLBACK registration in webserver_setup.cpp
installs webserver_impl::unescaper_func as a no-op pass-through. The
existing comment framed this purely as a libmicrohttpd v0.99 workaround
for an unescape bug where the internal MHD percent-decoder could produce
strings containing embedded NULs (e.g. from %00), which then broke
MHD_get_connection_values / MHD_lookup_connection_value lookups
downstream.
Verified against the upstream libmicrohttpd ChangeLog
(/opt/homebrew/Cellar/libmicrohttpd/1.0.5/ChangeLog) that upstream
resolved the embedded-NUL-in-key/value-storage class of bug by adding
explicit binary-zero-aware key/value storage and the size-carrying
MHD_KeyValueIteratorN callback. The relevant ChangeLog entries are:
Wed 20 Mar 2019 Adding additional "value_length" argument to
MHD_KeyValueIterator callback to support binary zeros
in values. -CG
Wed May 1 2019 Implemented MHD_KeyValueIteratorN with sizes for
connection's key and value to get keys and values
with binary zeros. -EG
Fri May 3 2019 Added functions for working with keys and values
with binary zeros. -EG
Sun Jun 09 2019 Releasing libmicrohttpd 0.9.64. -EG
configure.ac requires libmicrohttpd >= 1.0.0 (released 2024-02), which
is five years and dozens of releases past 0.9.64, so the v0.99 bug is
no longer reachable on any supported MHD version.
However, the no-op callback registration must stay. Per microhttpd.h
1849-1872 (MHD_OPTION_UNESCAPE_CALLBACK doc), registering a custom
unescape callback suppresses MHD's internal "%HH" decode. libhttpserver
relies on that suppression for two independent reasons:
1. Honouring a user-registered unescaper hook
(create_webserver::unescaper(...)). If MHD pre-decoded behind our
back, the user callback would run on already-decoded input — the
custom_unescaper integ test (test/integ/basic.cpp:2179) pins this.
2. Routing GET-arg decoding through the per-connection PMR arena
(unescape_in_arena() in src/detail/http_request_impl.cpp:265, wired
by TASK-072). Internal MHD decode would heap-allocate and double-
decode.
So this task does not remove the registration; it rewrites the comment
to make the architectural justification durable and demote the v0.99
bug-fix framing to a historical footnote with a verified version
cutoff. No #if MHD_VERSION guard is added: configure.ac already
enforces the floor at build time, so a runtime guard would be dead
code.
No behavioural change. The three pinning suites called out in the
plan stay green:
- test/unit/http_request_unescape_arena_test.cpp (8 tests / 12 checks)
- test/unit/http_request_arena_test.cpp
- test/integ/basic.cpp (custom_unescaper at line 2179, plus 96 others)
Full test/ suite: 100/100 PASS.1 parent 29a8eb2 commit 57bfb14
2 files changed
Lines changed: 30 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
340 | 340 | | |
341 | 341 | | |
342 | 342 | | |
343 | | - | |
344 | | - | |
345 | | - | |
346 | | - | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
347 | 367 | | |
348 | 368 | | |
349 | 369 | | |
| |||
0 commit comments