Hi,
HAProxy 2.6.34 was released on 2026/09/24. It added 32 new commits
after version 2.6.33.
This release fixes a number of bugs in the HTTP/3 and QUIC stacks, in the
HTTP message processing and in the Lua integration, along with several
smaller fixes and a startup failure when configuring "maxpipes" without
"maxconn".
* htx: Header length limits are now enforced on updates.
A header name is limited to 255 bytes and a header value to 1 MB minus one
byte. These limits were checked when a header was added, but not when an
existing one was rewritten with "replace-header" or "replace-value"
rules. When exceeded, the length silently overflowed into the block type,
corrupting the message. Since the header must first fit in a buffer, only
setups with "tune.bufsize" above 1 MB are affected; a client sending a
large enough header is then enough to trigger the issue. The same checks
are now applied on updates. The issue was reported by Adam Crawford.
An additional HTTP message buffer fix was backported as a precaution, to
prevent corruption when adding an empty block to a full buffer. Its only
known trigger is the decompression filter which only exists in 3.5-dev, so
no released version is known to be affected.
* h3/qpack: Several stalled transfers and compliance issues were fixed.
A transfer ending with an empty DATA frame could wait until timeout
instead of completing. This case now correctly signals the end of the
message. Empty HEADERS frames lacking the mandatory request information
are also rejected according to the protocol.
HTTP/3 header-compression control streams now release the space occupied
by data already processed, rather than becoming permanently stalled.
Invalid references to an unsupported dynamic compression table are also
rejected more strictly. Finally, HTTP/3 frame counters no longer count a
large frame several times just because it arrived in multiple pieces,
making the reported statistics more reliable.
* quic: More robust key updates and handling of delayed packets.
A failed memory allocation during a key update could cause a worker crash
on a subsequent key-phase change. HAProxy now retries key preparation and,
if necessary, drops the packet so that the peer can retransmit it, rather
than using missing keys. Delayed packets from the initial key phase are
also accepted correctly after the first key update, avoiding unnecessary
packet loss and retransmissions on connections with reordered traffic.
* quic: Connection timeout now armed for inactive connections.
The connection timeout was only armed once the first bytes were received,
so a connection on which nothing was ever received had no timeout at all
and could linger indefinitely. "timeout client" is now armed from
connection initialization, which guarantees that idle connections are
always closed as expected, and further reduces the risk of leaked
connections.
* hlua: A use-after-free in Lua cosockets was fixed.
Garbage collection of Lua sockets could release resources from the wrong
thread or access resources already freed, potentially crashing a worker.
This notably affected scripts loaded with "lua-load", whose state is
shared between threads. Socket cleanup is now handed back to the owning
thread. Closing a Lua socket that was never connected is also safe.
HTTP message duplication consistently returns nil when there is no data to
copy. Finally, memory associated with Lua rules is released during
configuration teardown; this was not a leak accumulating on each request
during normal operation.
* ssl: AES-GCM decryption on big-endian systems and a CA-file leak were fixed.
On 64-bit big-endian systems such as s390x and ppc64, the "aes_gcm_dec"
converter could corrupt memory and crash a worker when processing input.
The output-length handling has been corrected. This particular issue does
not affect the usual little-endian systems.
A small memory leak when deleting CA-file entries has also been fixed.
* sample: Strings carrying an embedded NUL byte could bypass ACLs.
The "url_dec", "json_query", "jwt_header_query" and "jwt_payload_query"
converters could produce a string containing a NUL byte (from "%00",
"\u0000" or a base64-decoded JSON). Such a string was then compared by "-m
str" on its prefix only, so "/public%00/admin" matched "/public" and an
allow-list could be bypassed. These converters now fail on such input,
like they already do on invalid sequences. Legitimate URLs and tokens are
not affected. Along with this, the configuration manual now describes the
exact contents allowed for each sample type.
* map: A crash with map_regm inside an ACL was fixed.
Using the "map_regm" converter in an ACL applied on a fetch that iterates
over several values, such as "req.hdr(name)" without an occurrence number,
crashed the process as soon as the first value did not match. The
converter was overwriting the internal iteration cursor of the fetch. A
single request was enough to trigger it, and the bug has existed since
1.7. The issue was reported by @Michael-JRead.
* http rules: capture rules evaluated in the backend context could crash.
Capture rules cannot be used on the backend side. However it is possible
to have such rules on a listener. In that case, when the listener was used
as a backend only, a crash could be experienced or the memory pools could
be corrupted because the capture slots were used in the context of a
frontend that never referenced them. Since such backend relationship can
only be resolved at run time, this could not be detected at startup. The
rules are now ignored for requests coming from another frontend, and the
documentation was updated to state that these capture slots only exist in
the section declaring them.
* http-htx: Rewriting the "Host" header of large requests could corrupt them.
When a "replace-header" rule rewrites the "Host" header of a request whose
URI contains an authority (all HTTP/2 and HTTP/3 requests, and HTTP/1
requests in absolute form), the URI's authority is updated to stay in sync
with the new value. This update was performed using on of rotating trash
chunk and could overwrite the new host value iteself, corrupting this way
the request. The authority update is now performed in a dedicated buffer,
so the forwarded request always remains consistent.
* http rules: Conditional "normalize-uri" rules could apply the wrong
normalizer.
When "percent-to-uppercase", "percent-decode-unreserved" or
"path-strip-dotdot" was used without its optional argument and directly
followed by an "if"/"unless" condition, the rule silently ended up as
"path-merge-slashes". Such rules now perform the configured
normalization. If you use them, be aware that URIs will now be rewritten
as intended, while they were previously left mostly untouched. The issue
was fixed by Youngkwang Lee.
* limits: Configuring "maxpipes" without "maxconn" could prevent startup.
Setting "maxpipes" while leaving "maxconn" to be calculated automatically
could make HAProxy refuse to start: the connection limit was calculated
without reserving the file descriptors needed for the configured pipes,
then rejected by the final resource checks. HAProxy now accounts for
"maxpipes" when sizing the connection limit, allowing such configurations
to start with a "maxconn" suited to the available file descriptors. There
is no longer a need to set "maxconn" explicitly to work around this issue.
Other few minor issues were also addressed:
* TLS inspection: SNI extraction was fixed to respect the extension's
boundaries.
* http fetch: "http_auth_bearer" used with a custom header was fixes to
work as expected in all cases
* http analysis: The transaction status code after early hints is now
properly restored to properly deal with internal responses, such as
deny rules.
* resolvers: Truncated DNS responses were misclassified. These responses
are now classified correctly, making DNS failures easier to diagnose.
* checks: HTTP health checks with several "host" headers could get
corrupted because an outdated request-line could be used. It is now
refreshed after each update.
Thanks to everyone for your help on this release!
Please find the usual URLs below :
Site index : https://www.haproxy.org/
Documentation : https://docs.haproxy.org/
Wiki : https://github.com/haproxy/wiki/wiki
Discourse : https://discourse.haproxy.org/
Slack channel : https://slack.haproxy.org/
Issue tracker : https://github.com/haproxy/haproxy/issues
Sources : https://www.haproxy.org/download/2.6/src/
Git repository : https://git.haproxy.org/git/haproxy-2.6.git/
Git Web browsing : https://git.haproxy.org/?p=haproxy-2.6.git
Changelog : https://www.haproxy.org/download/2.6/src/CHANGELOG
Dataplane API :
https://github.com/haproxytech/dataplaneapi/releases/latest
Pending bugs : https://www.haproxy.org/l/pending-bugs
Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs
Code reports : https://www.haproxy.org/l/code-reports
Latest builds : https://www.haproxy.org/l/dev-packages
---
Complete changelog :
Amaury Denoyelle (4):
BUG/MEDIUM: h3: do not block FIN on empty DATA frame
BUG/MINOR: h3: handle empty HEADERS frame as specified
BUG/MINOR: h3: only increment frame type counter on new header
BUG/MEDIUM: mux_quic: activate timeout on FE init
Christopher Faulet (12):
BUG/MEDIUM: hlua: Never release a cosocket applet from the GC
BUG/MINOR: hlua: Always return nil if there is no data to dup for HTTP
messages
BUG/MEDIUM: htx: Reserve a block descriptor for zero-sized blocks
BUG/MAJOR: htx: Check the header/trailer length limits when one is updated
BUG/MINOR: http-client: Convert server timeout ticks when setting it
BUG/MEDIUM: http-htx: don't build the new authority in a rotating trash
chunk
BUG/MEDIUM: http-act: ignore "capture len" rules evaluated from a backend
BUG/MEDIUM: tcp-rules: ignore "capture len" rules evaluated from a backend
BUG/MINOR: http-fetch: http_auth_bearer() must not match a missing header
BUG/MINOR: http-fetch: fix the space check of http_auth_bearer(<hdr>)
BUG/MINOR: tcpcheck: refresh the start-line after updating the authority
BUG/MINOR: http-ana: restore the transaction status after early hints
Frederic Lecaille (8):
BUG/MEDIUM: quic: crash on key update phase change after a failed one
BUG/MINOR: quic: late packets of the first key phase are dropped
BUG/MINOR: qpack: encoder and decoder stream data is never consumed
BUG/MINOR: qpack: accept a Required Insert Count which cannot be reached
BUG/MEDIUM: map: do not overwrite the fetch context in pat_match_regm()
REGTESTS: map: check map_regm inside an ACL over an iterating fetch
BUG/MINOR: sample: reject a \0 byte in url_dec, json_query and jwt_*_query
REGTESTS: http-rules: check "-m str" on a sample with an embedded \0
M9nx (1):
BUG/MINOR: hlua: release private Lua rule data on teardown
Manu Nicolas (1):
BUG/MINOR: resolvers: classify empty truncated responses
Remi Tricot-Le Breton (2):
BUG/MINOR: ssl: don't pass the address of a size_t as an int* to OpenSSL
BUG/MINOR: ssl: Fix leak of ca_list in cafile_entry
William Lallemand (1):
BUG/MINOR: payload: bound ClientHello extension lists by the extension
length
Willy Tarreau (2):
DOC: configuration: clarify the validity ranges of sample types
BUG/MEDIUM: limits: properly account for global.maxpipes in
compute_ideal_maxconn()
Youngkwang Lee (1):
BUG/MEDIUM: http_act: fix normalize-uri normalizer selection with a
condition
--
Christopher Faulet