Hi,
HAProxy 3.5-dev5 was released on 2026/08/21. It added 151 new commits
after version 3.5-dev4.
Once again, half of the commits are in fact bug fixes. We're still working
through the Mythos bug reports, which are designated as ANT-2026-xxxx in
the commit messages. None of them is particularly serious, which is great
and indicates that the previous passes have already ironed out the vast
majority of the problems. There are also a few other fixes that will
probably lead to a new series of stable releases soon to flush the pipe.
Other than that (and that's already a lot of work), some topics have been
particularly active over the last two weeks:
- update of libslz for decompression: in preparation for decompression
support, libslz was updated to the latest version which includes the
decompression work that Aurélien did. The decompression code already
works now but we're fighting against a truncation bug that happens
once in a while when recompressing behind, and that could be a
limitation of the filters API, so we preferred not delay its merge
rather than face strange bugs and discourage users from testing it
again. But I'm really impatient to see this merged, it managed to
reduce latency between two sites for responses as small as 10kB by
inserting haproxy in between!
- code size reduction: the BUG_ON() assertions used to represent up
to around 200 kB of code+messages depending on build options. And
when using DEBUG_STRICT >= 1 we also had the counters which also
reserve similar entries. The two were merged into a single unified
storage. We still have the same level of info, but save between
120k and 200k on the executable size.
- some refinement of the per-thread group FDs after an in-depth audit
of possible interactions. Pipes now have their limits split per group
(to avoid risks of starvation), "tune.idle-shared full" will now
complain when running in this mode, as well as "ssl-mode-async" and
"lua-load" (but "lua-load-per-thread" is fine of course).
- a new "fips_mode()" config predicate for .if/.endif blocks, that
allows to reserve/exclude some config parts when running in FIPS mode.
The current FIPS mode is also reported in "haproxy -vv".
- ssl samples: the ClientHello parsers were unified so that the
req.ssl_* sample fetch functions no longer rely on duplicated parsers.
A new "ssl_c_policies" sample fetch function was added to return the
X509v3 "Certificate Policies" extension.
- tune.defaults.purge, which says which "defaults" sections are going
to be purged, gained a new argument which is a list of words among
"proxies" and "servers", so that it is possible to reclaim unused
memory when certain not to use runtime server/proxy addition that
relies on defaults sections.
- a new "has_ctl" converter allows to detect control chars in a payload,
and these chars can be individually selected using a binary mask, or
a few less cryptic, symbolic keywords.
- the on-the-fly SSL certificate generator now uses a stronger seed for
its LRU cache key, because it was relatively easy to evict previously
generated certs from the cache. But this is essentially used for
debugging in MITM mode anyway.
And the rest is usual cleanups, debug, doc and regtests.
There are still some patches pending for review on the ML, they're not
lost, we're just lacking time to deal with everything that arrives from
multiple fronts at the moment, but that must not stop you from continuing
to contribute.
Also as predicted, the security list is progressively receiving more and
more reports for low-importance stuff. Please do not send non-critical
reports for issues that do not represent an imminent threat there. Regular
bugs are better discussed publicly where everyone can share their opinion,
either on this list or by issuing an issue on the GitHub issue tracker.
It's also how they will be handled the fastest.
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
Q&A from devs : https://github.com/orgs/haproxy/discussions
Sources : https://www.haproxy.org/download/3.5/src/
Git repository : https://git.haproxy.org/git/haproxy.git/
Git Web browsing : https://git.haproxy.org/?p=haproxy.git
Changelog : https://www.haproxy.org/download/3.5/src/CHANGELOG
Dataplane API :
https://github.com/haproxytech/dataplaneapi/releases/latest
OpenTelemetry : https://github.com/haproxytech/haproxy-opentelemetry
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
Willy
---
Complete changelog :
Amaury Denoyelle (7):
MINOR: config: support "all" and "none" on "tune.defaults.purge"
BUG/MINOR: proxy: release watcher in various commands on CLI abort
BUG/MINOR: proxy: release watcher in "show default-server" on CLI abort
REGTESTS: proxy: complete "del backend" test
BUG/MEDIUM: quic: prevent out-of-bound read on wrapping CRYPTO content
MINOR: quic: stress CRYPTO Rx buffer wrapping
BUG/MINOR: quic: drop multiple Retry on same connection
Aurelien DARRAGON (24):
MINOR: log/tools: fix ambiguous comments for some log encoding helpers
BUG/MEDIUM: log: always reserve room for trailing 0 when using CBOR
encoding helpers
BUG/MEDIUM: lua: resume Channel:send() from the unsent part of the string
BUG/MEDIUM: hlua_fcn: ensure systematic bref cleanup for patref list
iterator
IMPORT: slz: update slz to version 1.3.0
IMPORT: slz: do not read past the end of the input around the match loop
IMPORT: slz: fix the documented worst case size of flush() and finish()
IMPORT: slz: use the exact switch cost for the last literals of a block
IMPORT: slz: bound the bits wasted by the 9-bit literals
IMPORT: slz: do not append a block to an already finished stream
IMPORT: slz: fix the adler32 accumulators signedness on 32-bit
IMPORT: slz: avoid undefined shifts when building the word byte by byte
IMPORT: slz: clarify that the size promise applies to the stream, not to
a call
IMPORT: slz/uslz: fix incorrect sign extension in shift when reading the
adler32 trailer
IMPORT: slz/uslz: don't reset the drain offset when nothing was decoded
IMPORT: slz/uslz: don't lose the bytes consumed by the header fast paths
IMPORT: slz/uslz: make the gzip FEXTRA field resumable
IMPORT: slz/uslz: widen crc_flush, it overflowed on large stored blocks
IMPORT: slz/uslz: verify the trailer checksum before reporting completion
IMPORT: slz/uslz: decode all the members of a multi-member gzip stream
IMPORT: slz/uslz: add a method to impose an envelope format (gzip or zlib)
IMPORT: slz/uslz: inline the bit reader and the huffman decoders
IMPORT: slz/uslz: defer the output bookkeeping to a checkpoint
IMPORT: slz: prevent build compilation error due to unused
__slz_make_crc_table()
Dragan Dosen (1):
BUG/MEDIUM: fd: release the port range entry in host byte order
Frederic Lecaille (5):
BUG/MINOR: server: fix memory leak on "default-server" parsing failures
BUG/MINOR: h3: fix potential NULL pointer dereference in
_h3_trace_header()
BUG/MINOR: hq_interop: fix potential NULL dereference in _hq_trace_http()
BUG/MINOR: server: fix off-by-one error when parsing and copying source
port range
BUG/MINOR: qpack: missing shift count check in qpack_get_varint() (UB)
Juan Pablo Mora (2):
MINOR: ssl: add ssl_c_policies sample fetch
REGTESTS: ssl: add ssl_c_policies test
Kirill Furman (1):
BUG/MINOR: log: fix double-free error when error in parse_loger occurs
Mani Goyal (1):
BUG/MEDIUM: http: fix authority parsing for absolute-form URI with empty
path
Manu Nicolas (3):
BUG/MINOR: resolvers: accept fields at the response boundary
BUG/MINOR: dns: schedule idle task after setting its thread
CLEANUP: dns: centralize nameserver transport cleanup
Olivier Houchard (25):
BUG/MEDIUM: mux-fcgi: check the room left before appending the index
BUG/MEDIUM: spoe: clear the applet pointer when the applet fails to start
BUG/MINOR: mux-fcgi: don't call fcgi_strm_destroy() on a NULL stream
BUG/MEDIUM: http-ana: don't crash on "keep-query" in a response redirect
BUG/MEDIUM: stick-tables: use the same bucket for string keys with a NUL
BUG/MEDIUM: sock: bound the recvmsg() length when receiving old sockets
BUG/MEDIUM: http-ana: check the cookie rewrite result before moving the
offsets
BUG/MINOR: mux-fcgi: sanitize the STDERR records before logging them
MINOR: backend: Do not always allow takeover across thread groups
MINOR: backend: Deprecate tune.takeover-other-tg-connections.
DOC: Document limitations of tune.fd.tables
MEDIUM: pipes: Never allocate more than maxpipes
BUG/MEDIUM: bwlim: fix a stick-table entry leak in shared mode
BUG/MEDIUM: pollers: create the poller pipes in builds without threads
BUG/MEDIUM: tasks: don't type-pun state and tid in builds without threads
BUILD: protocol: silence -Warray-bounds in single-group builds
BUG/MEDIUM: tasks: don't type-pun state and tid in builds without threads
BUG/MEDIUM: pollers: really create the poller pipes in builds without
threads
REGTESTS: don't rely on the stick-table dump order in the ipmask test
MINOR: backend: Do not bother stopping if there is only one thread group
MINOR: ssl: Forbid using ssl-mode-async with per tgroup fd tables
MINOR: hlua: Forbid lua-load with per-tgroup fd tables
MINOR: addons/51d: Forbid use with per tgroup fd tables
MINOR: addons/wurfl: Forbid use with per tgroup fd tables
MINOR: addons/deviceatlas: Forbid use with per tgroup fd tables
Remi Tricot-Le Breton (7):
BUG/MEDIUM: jwe: validate the secret length against the algorithm of the
token
BUG/MINOR: jwt: don't take an extra reference on the certificate public
key
BUG/MEDIUM: ssl: require a full-length AEAD tag when decrypting with
AES-GCM
BUG/MINOR: conn: Do not check 'sess_el' list on frontend connections in
__trace_enabled
BUG/MINOR: ssl: Fix leak of X509_NAME in traces
BUG/MINOR: ssl: release the previous client cert reference at depth > 0
BUG/MEDIUM: ssl: Fix unprotected 'ssl_sock_choose_sni_ctx' calls
Rémi Tricot-Le Breton (3):
BUG/MEDIUM: cache: retain the primary or secondary entry only when
detaching its row
BUG/MINOR: cache: do not retain imcomplete or stripped secondary entry
BUG/MEDIUM: cache: do not release an entry under the cache read lock
William Lallemand (26):
BUG/MEDIUM: acme: don't delete a NULL token from the map
BUG/MINOR: ssl: reject server certificate names containing a NUL byte
BUG/MINOR: acme: restrict the permissions of the generated account key
DOC: config: clarify req.ssl_sni
BUG/MINOR: ssl: reject an embedded NUL in the ssl_*_dn(entry) fetches
BUG/MINOR: ssl: reject an embedded NUL in the full-DN ssl_*_dn() fetches
MEDIUM: ssl: add fips_mode() config condition predicate
MINOR: ssl: report FIPS mode in -vv for OpenSSL >= 3.0 too
REGTESTS: ssl: skip tests broken by FIPS mode
REGTESTS: checks: skip tcp-check-client-hello.vtc under FIPS mode
BUG/MINOR: payload: fix handshake length off-by-4 in ssl_hello_sni/alpn
MINOR: payload: make smp_fetch_ssl_hello_sni() use
smp_client_hello_parse()
MINOR: payload: make smp_fetch_ssl_hello_alpn() use
smp_client_hello_parse()
MINOR: ssl-gencert: use a 64-bit hash for the LRU cache key
MINOR: ssl-gencert: enforce a stronger seed for the LRU cache key
BUG/MINOR: spoe: check snprintf() return value in
spoe_set_var/spoe_unset_var
CI: github: add a TARGET=generic job in matrix.py
BUG/MEDIUM: ssl: enforce tune.ssl.lifetime across TLS1.3 session renewals
BUG/MINOR: ssl: apply tune.ssl.lifetime to TLS1.3 sessions on
BoringSSL/AWS-LC
BUILD: ssl: disable the TLS1.3 session timeout clamp on wolfSSL
BUG/MEDIUM: ssl: isolate TLS session resumption per X509 server
certificate
BUG/MINOR: ssl: isolate TLS session resumption per crt-list filter
BUG/MEDIUM: ssl: isolate TLS session resumption per authentication policy
CLEANUP: payload: remove dead code in smp_client_hello_parse()
BUG/MINOR: haproxy: fix out-of-scope tmpdir usage in do_chroot()
BUG/MINOR: ssl/cli: fix frontend-not-found detection in 'show ssl sni -f'
Willy Tarreau (45):
BUG/MEDIUM: hpack: encode long methods and schemes using the long form
BUG/MINOR: stats-file: reject tgid 0 when preloading shm objects
BUG/MINOR: hlua: use a local buffer to format the socket addresses
DEV: haring: bound the ring geometry to the size of the file
BUG/MINOR: connection: reserve the whole CRC32C TLV before saving its
pointer
BUG/MEDIUM: session: don't release a reversed connection twice on error
BUG/MINOR: lb-chash: bound the walk when the saved cursor changed tree
BUG/MINOR: debug: only dump the trace once in __BUG_ON_ONCE()
BUG/MINOR: mux-h2: strip the userinfo when deriving :authority for a
server
BUG/MINOR: quic: avoid a division by zero in the BBR pacing interval
DOC: security: clarify that only up-to-date versions may get securty
reports
MINOR: sample: add new converter has_ctl() to detect control characters
DEBUG: cli: unstatify cli_process_cmdline()
CLEANUP: debug: move ha_backtrace_to_stderr() declaration to bug.h
CLEANUP: debug: reorder definitions in bug.h
MINOR: debug: check the match count in __BUG_ON_ONCE() and not in
complain()
DEBUG: cli: add a "debug dev abort" debugging command
DEBUG: deduplicate __ABORT_NOW() between DEBUG_USE_ABORT and
ha_crash_now()
MINOR: debug: move printing of the hint to ha_backtrace_to_stderr()
MINOR: debug: use bit fields for the debug type and fatality
MINOR: debug: only emit and count warnings when explicitly requested
CLEANUP: debug: remove the now unused counter argument to complain()
MINOR: debug: make the complain() function start to complete the message
MEDIUM: debug: make the complain() function print the prefix
MEDIUM: debug: use \x1e (RS) to delimit the condition from vaargs in
DBG_COUNT()
MEDIUM: debug: use \x1e (RS) to delimit the condition from vaargs in
complain()
MEDIUM: debug: make the complain() function print the suffix
MINOR: debug: pass the type to the __BUG_ON*() macros
MINOR: debug: unify __BUG_ON() and __BUG_ON_ONCE()
MINOR: debug: avoid the break in __BUG_ON()
CLEANUP: debug: remove the unneeded do { } while (0) on __BUG_ON()
MINOR: debug: make a pair of __BUG_ON() for modern and obsolete linkers
MINOR: debug: rely on the __dbg_cnt_ counter for _BUG_ON_ONCE()
MINOR: debug: store the caller's details in debug_count
MINOR: debug: prepare complain() to be used in multiple ways
MEDIUM: debug: add a new version of complain() that takes a debug_count
struct
MEDIUM: debug: do not dump a context-less backtrace in ABORT_NOW()
CLEANUP: debug: make __BUG_ON() use abort_with_line()
MEDIUM: debug: merge the counter and message emission into complain()
MINOR: compiler: add a function attribute to disable tail calls
MINOR: debug: force complain's backtrace to be a tail jump instead of a
tail call
BUG/MINOR: uri-auth: never risk to dereference a NULL on error path
BUG/MINOR: mux-h2: harden h2_dump_h2s_info() against potentially null
h2s->sd
REGTESTS: converters: use connection: close in the has_ctl() test
BUG/MEDIUM: sink: pre-initialize the implicit log forwarding server
scientiamobile (1):
BUG/MINOR: wurfl: fix memory leak of information list and patch strings
at deinit
---